1. 程式人生 > >輸入聯想、搜尋智慧提示(Solr Suggest實現)

輸入聯想、搜尋智慧提示(Solr Suggest實現)

功能說明

  • 輸入聯想(搜尋智慧提示)是一個提高使用者體驗度的功能,使用者在使用檢索功能時輸入一個字母或者漢字時系統會自動給使用者推薦相關詞彙。此功能減少了使用者輸入時的敲擊次數,同時加快了輸入速度,還可以給使用者提供更多的檢索選擇。
  • Solr是一個高整合、獨立的企業級檢索伺服器。Solr配置簡單而且效能強大。本文使用了Solr自帶的Suggest元件來實現輸入聯想。Suggest是在Solr4之後才加入的,所以低於4的無法使用。本文使用的版本是4.3。
    在這裡插入圖片描述

專案配置

  • 在此預設已經配置好了solr環境。在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的時候,對拼寫檢查索引進行構建。(只有構建後,拼寫檢查才有效果)
  • <str name="spellcheck">true</str> : 開啟檢查建議
  • <str name="spellcheck.dictionary">suggest</str>:必須與searchComponent中spellchecker標籤下suggest配置對應
  • <str name="spellcheck.count">8</str> :配置拼寫檢查提示結果的個數(可以根據需要適當加大)
  • <str name="spellcheck.onlyMorePopular">true</str>:等於true,可以根據權重排序,開發時我一般讓他等於true
  • <arr name="components"> <str>suggest</str> </arr> : 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.同上,只不過放在最後工作
    名稱解釋部分摘自solr suggest檢查建議

注意* 按照上述配置後需要在solrcong.xml同級目錄下放置一個suggest.txt檔案。 suggest.txt檔案內容必須是utf-8的字元格式,不能用windows的記事本編輯。可以用notepad一類工具編輯轉UTF-8。方法如下:

在這裡插入圖片描述

Suggest.txt文字內容即為人工維護的熱搜詞,示例如下:

這裡寫圖片描述

配置完成後重啟solr伺服器,訪問solrAdmin。選擇對應的庫,點選Query、qt輸入"/suggest"、q輸入"筆"(搜尋詞)、點選Execute query檢視效果。右側輸出框為結果資料。

這裡寫圖片描述

程式碼呼叫

測試無誤後即可將這一模組運用到專案中了。實現思想是使用者在輸入框輸入內容後非同步訪問後天,後臺呼叫solr後封裝反回資料傳到前臺進行展示。java程式碼如下:

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;
	}

solr返回的結果如下:
{responseHeader={status=0,QTime=1},spellcheck={suggestions={筆{numFound=5,startOffset=10,endOffset=11,suggestion=[筆袋, 筆芯, 筆記本子, 膝上型電腦, 筆筒]},collation=GOODSNAME:筆袋}}}

  • 後臺將‘[筆袋, 筆芯, 筆記本子, 膝上型電腦, 筆筒]’做分割,將結果集合傳到前臺進行展示即可。