假设我们有一个电子商务网上,我们的搜索引擎是基于solr的。我们索引包含了几十万的文档(图书信息)。有一天市场部门的人到你的办公室提了需求。他们希望当用户搜索“machine”时,返回的结果和搜索“electronics”是一样的。你可能马上想到在建立索引的时候将“electronics”替换成“machine”。但是这不是一个很好的方案,因为你有很多文档包含“electronics”,并且你不修改整个数据库。在这个时候同义词搜索可以发挥作用了。下面就举个简单的例子。
怎么做1. 定义文档结构(将下面的配置添加到schema.xml的fields节点下):
<field name="id" type="string" indexed="true" stored="true"
required="true" />
<field name="description" type="text_syn" indexed="true"
stored="true" />
2. 定义text_syn类型:
<fieldType name="text_syn" class="cbcd-3f87-37f6-0a20 solr.TextField">
<analyzer type="query">
<tokenizer class="3f87-37f6-0a20-16d3 solr.WhitespaceTokenizerFactory"/>
<filter class="37f6-0a20-16d3-562b solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="index">
<tokenizer class="0a20-16d3-562b-0ea3 solr.WhitespaceTokenizerFactory"/>
<filter class="16d3-562b-0ea3-d0d3 solr.SynonymFilterFactory" synonyms="synonyms.
txt" ignoreCase="true" expand="false" />
<filter class="4a05-a772-3171-0264 solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
3. 定义synonyms.txt文件:
machine => electronics
synonyms.txt文件必须和其他配置文件一样放在conf目录下。
4. 最后,我们通过solr管理员界面检查同义词是否被solr所识别:
分析首先我们定义了文档结构。文档包含两个字段id和description。“description”的类型是“text_syn”。“text_syn”基于“solr.TextField”类,包含两个分析器,一个是在索引阶段,另一个是在查询阶段。查询阶段分析器包含一个使用空格来切分文本的分词器和将词汇单元(分词器切分后的结构)转换为小写的过滤器。索引阶段的分析器包含和一样的分词器和同义词过滤器。同义词过滤器和其他过滤器一样有一个factory类定义。属性“synonyms”定义了同义词存放的文件位置。”ignoreCase“属性告诉solr词汇单元和同义词不区分大小写。属性“expand”设置为false,则表示一行词语中,第一个词语和它之后的词语是同义词。当设置为“true”,一行词语中,每两个词语都是同义词。
放的synonyms.txt文件告诉solr当“text_syn”类型的域里出现“machine”时,使用“electronics”替代。synonyms.txt文件中的一行就对应一份同义词匹配规则。文件必须使用UTF-8格式。
在上面的截图中,你会发现同义词在索引里生效了。
等效同义词设置让我们回顾下上面的例子。如果市场部的人不仅仅想要用户在搜索“machine”时返回搜索“electronics”的结果,同时希望当搜索“machine”时所有含有“electronics”的书籍在结果集里。解决方案很简单。我们只需要在synonyms.txt文件配置如下,并且设置expand为true:
machine, electronics
正如我们前面所说,expand为true时,词之间互为同义词。