Solr4 智能提示Suggest

系统 1567 0

 

一、背景

  搜索的智能提示是一个搜索应用的标配,主要作用是避免用户输入错误的搜索词,并将用户引导到相应的关键词上,提升用户体验。

  由于中文的特点,如果搜索自动提示可以支持拼音的话会给用户带来更大的方便,免得切换输入法。

二、目标

    • 基于用户的历史搜索关键字进行提示
    • 同时支持汉字,拼音输入
    • 支持前缀匹配,比如输入“ch”可能提示出“重庆”
    • 支持缩写输入,比如输入“cq”能提示出“重庆”
    • 多音字支持,比如输入“chongqing”或者“zhongqing”都能提示出“重庆”
    • 输出结果,根据用户查询关键字的频率进行排序,暂时不考虑个性化需求

三、分析与解决方案

       假设我们的搜索应用是基于solrcloud实现的,主要是对商家信息进行搜索,包括商家名称(store_name)、商家地址(address)。

       (1). 用户每天输入大量的查询关键字,我们把查询的关键字记录下来,目前通过异步队列写入到mysql中,后期考虑写入到hbase中

       (2). 用户输入的关键字可能是汉字、数字,英文,拼音,特殊字符等等,由于需要实现拼音提示,所以我们需要把汉字转换成拼音,java中考虑使用pinyin4j组件实现转换。

       (3). 汉字转换拼音的过程中,顺便提取出拼音缩写,如“chongqing”,"zhongqing"--->"cq","zq"

       (4). 要支持多音字提示,对查询串转换成拼音后,需要实现一个全排列组合,考虑到查询串可能比较长导致全排列比较的,具体算法需要做限制处理。

 

Solr Suggest实现智能提示

     首先Solr作为一个应用广泛的搜索引擎系统,它内置了智能提示功能,叫做Suggest模块。该模块有两种可选方案做智能提示:

      (1)、基于提示词文本做智能提示

      (2)、基于索引中得某个字段建立索引词库做智能提示

     suggest的配置相对简单, 下面开始写 主要是使方式, 自定义的建议词文本,放在跟solrconfig.xml同一级目录下即可

     例如:solr\solr_home\collections\collection1\conf\suggest.txt 

 

下面给出suggest在solrconfig.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">my_word</str>  

        <
      
        float
      
       name="threshold">0.0001</
      
        float
      
      > 

        <!--
      
         使用自定义suggest词库词--> 

        
      
      <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 ="org.apache.solr.handler.component.SearchHandler"> <lst name="defaults"> <str name="spellcheck"> true </str> <str name="spellcheck.dictionary">suggest</str> <str name="spellcheck.count">10</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>

说明:

 1.solr的suggest基于solr.SpellCheckComponent

 2.queryAnalyzerFieldType 参数为string,在这不要定义复杂分词,如果是根据某一个索引字段,意义不大

 3.field字段名,表示基于schema中的某一个索引字段

 4.threshold限制一些不常用的词出现,值越大过滤纸越多

 5.sourceLocation用于设置字典,如果有一个字典能记录用户常搜索的字, 更灵活的控制,可以存放一些高质量的 query短语

 6.spellcheckIndexDir如果已经设置spellcheck,那么可以在此制定目录

 7.字典格式如下

# This is a sample dictionary file.

acquire

accidentally\t2.0

accommodate\t3.0

文本格式utf-8,#开头表示注释,被忽略

每一个词一行,后面带权重

 8.配置词典后在requestHandler中设置spellcheck.onlyMorePopular为true,可以根据权重排序

 9.spellcheck.count返回行

  配置完成重启服务后,设置参数suggest/?spellcheck.build=true来创建spellchecker的索引

 然后输入:http://ip:port/corename/suggest?q=xxx进行搜索了

 接下来就是前台js实现的问题了。

 当然也可以通过solrj来进行搜索

      CommonsHttpSolrServer server = 
      
        new
      
      
         CommonsHttpSolrServer(

                
      
      "http://ip:port/corename/"
      
        );

    SolrQuery params 
      
      = 
      
        new
      
      
         SolrQuery();

        String token 
      
      = "Solr"
      
        ;

        params.set(
      
      "qt", "/suggest"
      
        );

        params.set(
      
      "q"
      
        , token);

        params.set(
      
      "spellcheck.build", "true"
      
        );

        QueryResponse response 
      
      = 
      
        null
      
      
        ;

        
      
      
        try
      
      
         {

            response 
      
      =
      
         server.query(params);

            System.out.println(
      
      "查询耗时:" +
      
         response.getQTime());

        } 
      
      
        catch
      
      
         (SolrServerException e) {

            System.err.println(e.getMessage());

            e.printStackTrace();

        } 
      
      
        catch
      
      
         (Exception e) {

            System.err.println(e.getMessage());

            e.printStackTrace();

        } 
      
      
        finally
      
      
         {

        } 

        SpellCheckResponse spellCheckResponse 
      
      =
      
         response

                .getSpellCheckResponse();

        
      
      
        if
      
       (spellCheckResponse != 
      
        null
      
      
        ) {

            List
      
      <Suggestion> suggestionList =
      
         spellCheckResponse

                    .getSuggestions();

            
      
      
        for
      
      
         (Suggestion suggestion : suggestionList) {

                System.out.println(
      
      "Suggestions NumFound: "

                        +
      
         suggestion.getNumFound());

                System.out.println(
      
      "Token: " +
      
         suggestion.getToken());

                System.out.print(
      
      "Suggested: "
      
        );

                List
      
      <String> suggestedWordList =
      
         suggestion.getAlternatives();

                
      
      
        for
      
      
         (String word : suggestedWordList) {

                    System.out.println(word 
      
      + ", "
      
        );

                }

                System.out.println();

            }

        }
      
    

 

-----OK

 

Solr4 智能提示Suggest


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论