Solr6.5配置中文分詞器

 

Solr做爲搜索應用服務器,咱們在使用過程當中,不可避免的要使用中文搜索。如下介紹solr自帶的中文分詞器和第三方分詞器IKAnalyzer。java

 注:下面操做在Linux下執行,所添加的配置在windon下依然有效。web

運行環境面試

    •   Solr:6.5.1
    •   系統 : Linux

 

如下是設置 solr中文分詞器的方法。apache

注:開始以前,假定你已經成功登陸solr的界面,並建立了core。tomcat

一:使用solr自帶 中文分詞器服務器

一、進入解壓好的solr文件夾根目錄下執行如下命令app

1 cp ./contrib/analysis-extras/lucene-libs/lucene-analyzers-smartcn-6.5.1.jar /opt/tomcat-solr/webapps/solr/WEB-INF/lib/ 

複製lucene-analyzers-smartcn-6.5.1.jar該文件到 Tomcat下的 solr web應用中的lib目錄下,不清楚的能夠看 執行命令的地址。複製的文件就是 solr自帶的中文分詞器。webapp

注:若是沒有解壓的目錄,那麼在solrhome的目錄下也存在contrib這個文件夾,若是你已經成功登陸過solr界面的話。ide

 

二、進入core目錄下的conf文件夾,測試

打開 managed-schema文件,跳至文件最後,在最後添加新的字段類型以下

1 <!--solr cnAnalyzer-->
2   <fieldType name="solr_cnAnalyzer" class="solr.TextField" positionIncrementGap="100">
3       <analyzer type="index">
4         <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
5       </analyzer>
6       <analyzer type="query">
7         <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
8       </analyzer>
9   </fieldType>
 

  fieldType: 字段類型屬性

name: 字段類型名稱(能夠理解爲Java的 數據類型名稱。例如: int、double、String等Java中的數據類型名稱)

class: 數據類型(默認文本數據便可,還有其餘的例如:字符串、浮點、整形等)
看下面的配置文件中 其餘字段類型,應該很容易理解了:

1  <!-- 字符串 -->
2    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
3  <!-- 布爾類型 -->
4    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
5  <!-- 整形 -->
6     <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
7  <!-- 浮點 -->
8     <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
  positionIncrementGap:一個doc中的屬性有多個值時候,設置每一個屬性之間的增量值和multiValued屬性配合使用(避免錯誤匹配)。
  type: 分詞生效的範圍,兩個參數分別是 index和query,表示 建立索引和搜索時候都生效。不寫默認狀況下二者均生效。
 

 三、添加完畢以後,保存退出並從新啓動 Tomcat服務器,繼續訪問solr。在建立的core中 Analyzer測試中文分詞結果以下。

 測試以後,能夠看到 短語確實被分割了,可是有些中止詞沒有被去掉(的、是),也沒有去除符號(,),能夠在屬性上添加 words添加停詞字典。那麼咱們下面試試第三方的分詞器.

 

二:solr 第三方中文分詞器 IKAnalyzer

  在使用IKAnalyzer分詞器以前,先說明因爲做者在12年以後沒有更新,致使舊版本的分詞器和新版本的solr沒法匹配。所以在源碼的基礎上作些改動,以兼容新版的solr。

一、首先修改分詞器:

IK的分詞器 IKTokenizer類實現了抽象類Tokenizer。在IKTokenizer的構造方法中調用了父類Tokenizer的構造方法,代碼以下

1   public IKTokenizer(Reader in, boolean useSmart) { 2       super(in); 3       offsetAtt = addAttribute(OffsetAttribute.class); 4       termAtt = addAttribute(CharTermAttribute.class); 5       typeAtt = addAttribute(TypeAttribute.class); 6       _IKImplement = new IKSegmenter(input, useSmart); 7   }

Tokenizer構造器:

1 protected Tokenizer(AttributeFactory factory) {
2     super(factory);
3   } 

能夠看到上面的代碼中,構造器調用了父類的構造器,出現不兼容的緣由是由於如今的抽象類Tokenizer的構造方法中接受的是 AttributeFactory這個類型,而IKTokenizer傳遞的Reader不匹配。因此在此基礎上作了以下修改

 1     //分析器調用
 2     public IKTokenizer(Reader in, boolean useSmart) {  3         offsetAtt = addAttribute(OffsetAttribute.class);  4         termAtt = addAttribute(CharTermAttribute.class);  5         typeAtt = addAttribute(TypeAttribute.class);  6         _IKImplement = new IKSegmenter(input, useSmart);  7  }  8     
 9     //分詞器工廠調用
10     public IKTokenizer(AttributeFactory factory, boolean useSmart) { 11         super(factory); 12         offsetAtt = addAttribute(OffsetAttribute.class); 13         termAtt = addAttribute(CharTermAttribute.class); 14         typeAtt = addAttribute(TypeAttribute.class); 15         _IKImplement = new IKSegmenter(input, useSmart); 16     }

在第一個代碼中刪除了調用父類構造器的過程,主要用於分析器調用,而後第二個是由於 在設置配置文件managed-schema中設置分析器和構造器結合使用的時候須要用到工廠類,所以在此處也建立了一個新的構造方法,接收一個AttributeFactory類型的參數 ,下面會看到他的用處。

 

二、分析器 IKAnalyzer。

IK分析器中IKAnalyzer重寫父抽象類Analyzer中的createComponents方法,原代碼以下

1   /**
2  * 重載Analyzer接口,構造分詞組件 3    */
4  @Override 5   protected TokenStreamComponents createComponents(String fieldName, final Reader in) { 6       Tokenizer _IKTokenizer = new IKTokenizer(in, this.useSmart()); 7     return new TokenStreamComponents(_IKTokenizer); 8   }

因爲如今的Analyzer的抽象方法createComponents,只須要一個 fieldName參數,並不須要Reader,所以直接刪除Reader便可。同時由於分詞器中也不須要Reader對象,在原來的分詞器IKAnalyzer是接收Reader對象後又傳遞給了父類的構造器,可是在新版的solr中不須要了,並且分詞器IKAnalyzer中也沒有使用該對象。

1  @Override 2     protected TokenStreamComponents createComponents(String fieldName) { 3         IKTokenizer it = new IKTokenizer(useSmart); 4         return new Analyzer.TokenStreamComponents(it); 5     }

其實並沒更改什麼,去掉了Reader,而後建立分詞器實例返回。若是這時候在managed-schema配置文件中設置分析器已經可使用了 以下:

1 <fieldType name="IK_cnAnalyzer" class="solr.TextField">
2   <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
3 </fieldType>

  直接指定修改後的IK分詞器給分析器。在單獨給分析器指定分詞器時候,不要在 fieldType(字段類型) 加上positionIncrementGap 參數,不然會報錯:

  java.lang.RuntimeException: Can't set positionIncrementGap on custom analyzer class org.wltea.analyzer.lucene.IKAnalyzer

  直接使用solr中文分析器時候,一樣沒法指定 fieldType 的 屬性positionIncrementGap,那麼應該 solr在直接設定 分析器的時候是沒法指定該屬性的。

 注:analyzer(分析器)上還能夠設置 type屬性,告訴solr在何時會生效。分別是index和query,在建立索引時候生效,在查詢時候生效。默認不寫同時生效.

   class:直接指定的分析器(Analyzer)不能是分詞的工廠類(Factory)或者分詞器(Tokenizer)

上面的修改已經可使用分析器了,可是若是和分詞器和過濾器配合使用,那麼必須建立一個能夠生產分詞器的工廠類。該工廠類實org.apache.lucene.analysis.util.TokenizerFactory抽象類.並且必須實現create方法。

同時還要在構造器中調用父接口的構造器,並傳遞一個Map類型的參數。

 

三、IKTokenizerFactory工廠類

 1 package org.wltea.analyzer.lucene;  2 
 3 import java.util.Map;  4 
 5 import org.apache.lucene.analysis.Tokenizer;  6 import org.apache.lucene.analysis.util.TokenizerFactory;  7 import org.apache.lucene.util.AttributeFactory;  8 
 9 /**
10  * IK分詞工廠類。 用於配置文件中 分析器添加分詞器(必須工廠類)。 11  */
12 public final class IKTokenizerFactory extends TokenizerFactory { 13 
14     private boolean useSmart; 15 
16     // 從頁面傳遞的值中。設置 useSmart 的值
17     public IKTokenizerFactory(Map<String, String> args) { 18         super(args); 19         /*
20  * 判斷Map容器中是否存在useSmart的能夠,若是有獲取該key對應的value。 21  * 若是沒有,則設置默認值,也就是第三個參數 false 22          */
23         useSmart = this.getBoolean(args, "useSmart", false); 24         if (!args.isEmpty()) { 25             throw new IllegalArgumentException("Unknown parameters: " + args); 26  } 27  } 28 
29  @Override 30     public Tokenizer create(AttributeFactory factory) { 31         return new IKTokenizer(factory, useSmart); 32  } 33 }

  能夠看到該分詞器實現父類的create方法時候接受了一個AttributeFactory, 是否是很熟悉,在上面修改的IKTokenizer中新增的構造器內接受該類型的參數,並調用父類的構造器,又將參數傳遞給了父類。

  所以IKTokenizer中的第二個構造器就是用於該工廠調用並傳遞參數,而後建立實例返回。

  至於另一個問題,構造器必須調用父類的構造器,而後建立Map類型的參數,傳遞給父類構造器,是由於父類TokenizerFactory只有一個帶參數的構造器,沒有默認構造器。子類IKTokenizerFactory在初始化過程當中,必須調用父類的構造器。即便傳遞null值給父類。

  而Map容器的做用是:在配置文件managed-schema中,設置分詞器的時候,能夠傳遞參數。用於設置分詞器中的參數,例如上面的 useSmart,就是用於IK分詞器是否開啓智能分詞的關。

  至此修改所有完畢,最後只須要將修改後的編譯文件放入 IK的jar包內便可。注意包路徑爲

org.wltea.analyzer.lucene

  若是以爲修改麻煩,能夠直接下載修改後的文件  下載地址:點我下載 壓縮包內包含了 修改後的文件,和 IK的源碼等。

  

  四、IK在Linux上的設置方式

  先將IK的jar文件和配置文件上傳到Linux系統中

複製 IK jar包到 solr/WEB-INF/lib 目錄下

1 cp IKAnalyzer2012FF_u1-6.51.jar /opt/tomcat-solr/webapps/solr/WEB-INF/lib/

複製配置文件到 solr/WEB-INF/classes目錄下

1 cp ext.dic IKAnalyzer.cfg.xml stopword.dic /opt/tomcat-solr/webapps/solr/WEB-INF/classes/

  進入solrhome中打開managed-schema文件,添加IKAnalyzer

  個人路徑配置路徑:/opt/tomcat-solr/solrhome/home/mycore/conf  請根具我的路徑修改配置文件

  

  五、在上問添加solr中文分詞器後面重現加入如下代碼

 1 <!-- IKAnalyzer -->
 2 <fieldType name="IK_cnAnalyzer" class="solr.TextField" positionIncrementGap="100">
 3      <analyzer type="index">
 4       <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false"/>
 5     </analyzer>
 6      <analyzer type="query">
 7          <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false"/>
 8       </analyzer>
 9  </fieldType>
10  
11   <!-- IKAnalyzer Field-->
12   <field name="IK_content" type="IK_cnAnalyzer" indexed="true" stored="true"/>

注:若是在操做以前,經過solr界面的 AddField 方式添加了新的字段,那麼 配置文件 中的數據會被solr所有從新更改,字段類型出如今第一行。全部請根據狀況修改配置文件

 

  在analyzer(分析器)中設置了 index和query說明建立索引和查詢的時候都使用分詞,所以若是有特殊要求,能夠指定索引和查詢時候設置不一樣的分詞器。

  useSmart爲工廠對象的構造方法接受的參數,就是上面說到的分詞工廠類中的 Map接受該參數。設置是否使用智能分詞.默認爲false,使用細粒度分詞

注:此處的 class只能是工廠對象,並由工廠對象負責建立分詞器實例。工廠對象須要繼承org.apache.lucene.analysis.util.TokenizerFactory這個抽象類,並實現其中的create方法,實現的工廠對象必須用final修飾。

   添加分詞結果後的managed-schema文件以下:

 

六、添加完保存以後,從新訪問 solr,而後在 core的 Analyzer中測試結果以下

 

 由於新增的字段 IK_content,指定的字段類型是IK_cnAnalyzer,該類型使用的是IK中文分詞器,因此使用指定字段或者字段類型,分詞結果是同樣的。

 

七、設置ik的擴展詞庫,

在/opt/tomcat-solr/webapps/solr/WEB-INF/classes 目錄下的能夠設置 ik的擴展字典

 

如今打開配置文件 IKAnalyzer.cfg.xml,

而後在打開擴展字典 配置文件 ext.dic 添加 全文搜索、服務器。而後重啓 Tomcat。

 

八、重啓Tomcat服務器以後,繼續分詞查看結果以下

 

很顯然擴展字典生效了,出現了新增的全文搜索、服務器兩個詞組,所以若有須要能夠在擴展字典中添加詞組。至於後面重複出現詞組(分詞後的),是由於IK分詞子默認開啓了細粒度的分詞,若是須要開啓智能分詞能夠將配置文件中的 useSmart 設置爲true便可。 下面是開啓智能分詞後的結果:

  能夠根據需求是否開啓智能分詞,至此solr的中文分詞到此結束。

  總結:

    設置solr的分詞只須要將分詞器的jar包放入solr的依賴文件內,而後在覈心core中的managed-schema設置須要的分詞便可。

 文章有不少不足的地方,歡迎你們指正!

相關文章
相關標籤/搜索