说到搜索,联想词功能肯定是必备的。为实现基于solr的联想词功能,做了大量的调研,最终在项目中实现了两种方案混用的形式。第一种是基于分词器推荐功能,即spellcheck;第二种是利用自己生成词库的方式去实现联想。那说一下这两种在solr里的实现方式吧。
- 首先是基于分词器推荐的方式,在solrconfig.xml中添加并设置suggest组件,实现如下:
在solrconfig.xml中修改如下配置,然后重启solr。
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<str name="queryAnalyzerFieldType">text_ik</str>
<lst name="spellchecker">
<str name="name">default</str>
<str name="field">searchText</str>
<str name="buildOnCommit">true</str>
<str name="spellcheckIndexDir">spellchecker</str>
</lst>
</searchComponent>
<searchComponent class="solr.SpellCheckComponent" name="suggest">
<str name="queryAnalyzerFieldType">text_ik</str>
<lst name="spellchecker">
<str name="name">suggest</str>
<str name="classname">org.apache.solr.spelling.suggest.Suggester</str>
<str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>
<str name="field">searchText</str>
<!-- the indexed field to derive suggestions from -->
<float name="threshold">0.0001</float>
<str name="spellcheckIndexDir">spellchecker</str>
<str name="comparatorClass">freq</str>
<str name="buildOnOptimize">true</str>
<str name="buildOnCommit">true</str>
</lst>
</searchComponent>
<requestHandler class="org.apache.solr.handler.component.SearchHandler" name="/suggest">
<lst name="defaults">
<str name="spellcheck">true</str>
<str name="spellcheck.dictionary">suggest</str>
<str name="spellcheck.onlyMorePopular">true</str>
<str name="spellcheck.extendedResults">false</str>
<str name="spellcheck.count">10</str>
<str name=“spellcheck.collate">true</str>
<str name="spellcheck.maxCollations">5</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
<queryConverter name="phraseQueryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>
需要说明的是,上面配置中主要注意field字段和queryAnalyzerFieldType字段的配置,前者是你再manage-scheme中配置过的field,后者是fieldType。下面是一个请求后的示例,访问URL为:http://[solr-sever-ip]:8983/solr/[coreName]/suggest?indent=on&q=防火设计&wt=json。
{
"responseHeader":{
"status":0,
"QTime":2},
"spellcheck":{
"suggestions":[
"防火",{
"numFound":7,
"startOffset":0,
"endOffset":2,
"suggestion":["防火门",
"防火墙",
"防火设计",
"防火阀",
"防火间距",
"防火堤",
"防火板"]},
"设计",{
"numFound":9,
"startOffset":2,
"endOffset":4,
"suggestion":["设计规范",
"设计标准",
"设计图",
"设计说明",
"设计方案",
"设计阶段",
"设计人",
"设计院",
"设计变更"]}],
"collations":[
"collation","防火设计规范",
"collation","防火门设计",
"collation","防火墙设计",
"collation","防火设计标准",
"collation","防火门设计规范"]}}
而我在联想词的选择中选择的不是suggestion(因为会对分词结果产生多个),最终我采用了collations(通过配置maxCollations设置想要的结果数)。然而这种效果不是非常理想,缺点就是当推荐的分词越来越长时,会产生语句不通的推荐。我的做法是通过一些策略过滤那种情况,然而为了更好的联想体验,我又实现了第二种方式的联想功能。
2. 基于自建联想词库方式。
首先创建一个新的core,方式参考之前的文章。然后修改配置文件solrconfig.xml,与上面基本一致,需要注意到sourceLocation为自建词库的地址,每次更改自建词库需要重启solr才能生效。
这种方式也有弊端,如果你的自建词库不够全的话,会产生无推荐的情况。因此我最终将这两种方式同时运用,如果有比较好的方案,希望各位能够指点一下!多谢!<searchComponent name="suggest" class="solr.SpellCheckComponent"> <str name="queryAnalyzerFieldType">text_ik</str> <lst name="spellchecker"> <str name="name">suggest</str> <str name="classname">org.apache.solr.spelling.suggest.Suggester</str> <str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str> <str name="field">searchText</str> <float name="threshold">0.0001</float> <str name="sourceLocation">suggest/suggest.txt</str> <str name="spellcheckIndexDir">spellchecker</str> <str name="comparatorClass">freq</str> <str name="buildOnOptimize">true</str> <str name="buildOnCommit">true</str> </lst> </searchComponent> <requestHandler name="/suggest" class="solr.SearchHandler"> <lst name="defaults"> <str name="spellcheck">true</str> <str name="spellcheck.dictionary">suggest</str> <str name="spellcheck.count">5</str> <str name="spellcheck.onlyMorePopular">true</str> <str name="spellcheck.extendedResults">false</str> <str name="spellcheck.collate">true</str> <str name="spellcheck.maxCollations">5</str> </lst> <arr name="components"> <str>suggest</str> </arr> </requestHandler>