Solr Suggest搜索智能提示、输入联想

1.背景介绍

  • Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过HttpGet操作提出查找请求,并得到XML格式的返回结果.在电商项目的检索场景下,存在因用户输入的搜索词汇不准确导致搜索结果不理想的情况。而solr的suggest模块可以合理的解决这一难题。

效果如下图:

这里写图片描述

2.项目配置

在此默认已经配置好了solr环境,配置suggest模块需要在solrhome下的solrcong.xml文件中加入如下配置:
  <searchComponent name="suggest" class="solr.SpellCheckComponent">    
    <str name="queryAnalyzerFieldType">string</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">GOODSNAME</str>    
      <float name="threshold">0.0001</float>   
      <str name="sourceLocation">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">      -->
<requestHandler name="/suggest" class="org.apache.solr.handler.component.SearchHandler">      
  <lst name="defaults">      
      <str name="spellcheck">true</str>      
      <str name="spellcheck.dictionary">suggest</str>      
      <str name="spellcheck.count">11</str>      
      <str name="spellcheck.onlyMorePopular">true</str>    
      <str name="spellcheck.extendedResults">false</str>          
      <str name="spellcheck.collate">true</str>    
      <!--<str name="spellcheck.build">true</str>  -->      
  </lst>      
  <arr name="components">      
      <str>suggest</str>      
  </arr>      
</requestHandler>  

配置名称解释:
queryAnalyzerFieldType : schema.xml中的fieldType类型,如果加了这个选项,拼写检查时会调用这个fieldType的分词器,如果没有加,solr会取field属性上面filetype的分词器,这个时候还找不到,solr会创建一个按空格进行分词(SpellCheckComponent需要一个分词器才能运行),在这们项目中,我们现希望Analyzer不对查询做任何的改变,因此选择string。(网上也建议不要对他定义复杂的分词,如果指定的Analyzer很复杂的话,会导致suggest返回的结果不符合预期)
name:就是取个名字,江湖中的人士都是让他等于suggest
classname :org.apache.solr.spelling.suggest.Suggester(不要改动)
lookupImpl :org.apache.solr.spelling.suggest.Suggester(不要改动)
field : 说明只在这个字段上面做拼写检查
threshold :限制一些不常用的词出现,值越大过滤词就越多,取值范围【0~1】官网默认是0.005
comparatorClass : ellchecker组件中的comparatorClass参数可配置Suggest返回结果的排序,目前有如下几种可选方案:
a .Empty – in which case the default is used. 默认就是这个
b.score – explicitly choose the default case
c.freq – Sort by frequency first, then score. 通过频率的第一排序,然后得分 (开发时用这个)
d.A fully qualified class name – Provide a custom comparator that implements Comparato

buildOnCommit : 取值true或者flase,当commit的时候,对拼写检查索引进行构建。(只有构建后,拼写检查才有效果)
buildOnOptimize :当optimize的时候,对拼写检查索引进行构建。(只有构建后,拼写检查才有效果)
true : 开启检查建议
suggest :必须与searchComponent中spellchecker标签下suggest配置对应
8 :配置拼写检查提示结果的个数(可以根据需要适当加大)
true :等于true,可以根据权重排序,开发时我一般让他等于true
suggest : handler拥有的 components,first-components,last-components这三个属性的剖,Solr的handler都是同过这三个属性来取他所依赖的components(组件)
备注:handler在运行时,会加载5个默认的组件
a如果配置了components,则SOlr不会运行默认的5个组件。
而且你配置的first-components,last-components两个都是无效的。
b.如果配置了first-components,SOlr会给handler添加5个默认的组件时,同时会添加first-components配置的组件,而且这个组件最先工作。
c.同上,只不过放在最后工作

按照上述配置好项目后需要放置一个suggest.txt文本文件在solrcong.xml同级目录下
注意 : suggest.txt文件内容必须是utf-8的字符格式,不能用windows的记事本去编辑,可以用比如notepad一类工具编辑。或者在记事本编辑好了使用notepad转换文本格式,方法如下:
这里写图片描述

Suggest.txt文本内容即为人工维护的热搜词,示例如下:
这里写图片描述

3.测试

配置完成后重启solr服务器,访问主页,按照下图步骤即可看到推荐效果
这里写图片描述

4.项目配置

测试无误后即可将这一模块运用到项目中了,主体思想是:当用户在输入框输入内容后异步访问服务器,服务器返回数据到前台,列表展示。服务器代码如下:

public List<String> searchSuggest(String word) throws SolrServerException {
        SolrQuery params = new SolrQuery();  
        params.set("qt", "/suggest");  
        params.setQuery("GOODSNAME:"+word);//word为搜索词
        QueryResponse queryResponse = getSolrServer(ResourceUtil.getConfigValueByName("solr.url")).query(params);
        SpellCheckResponse suggest = queryResponse.getSpellCheckResponse();    
        List<Suggestion> suggestionList = suggest.getSuggestions();    
        List<String> suggestedWordList  = new ArrayList<String>();
        for (Suggestion suggestion : suggestionList) {    
            System.out.println("Suggestions NumFound: " + suggestion.getNumFound());    
            System.out.println("Token: " + suggestion.getToken());    
            suggestedWordList = suggestion.getAlternatives();    
        }   
        System.out.print("Suggested: "+queryResponse);    
        return suggestedWordList;
    }

检索返回的结果如下:
{responseHeader={status=0,QTime=1},spellcheck={suggestions={笔={numFound=5,startOffset=10,endOffset=11,suggestion=[笔袋, 笔芯, 笔记本子, 笔记本电脑, 笔筒]},collation=GOODSNAME:笔袋}}}

文中部分内容摘自:http://eksliang.iteye.com/blog/2097924

水平有限,不免有误,不恰当的地方请指出,不胜感激!

猜你喜欢

转载自blog.csdn.net/leo187/article/details/78698574