Solr6.5配置中文分詞器


 

Solr作為搜索應用服務器,我們在使用過程中,不可避免的要使用中文搜索。以下介紹solr自帶的中文分詞器和第三方分詞器IKAnalyzer。

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

運行環境

    •   Solr:6.5.1
    •   系統 : Linux

 

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

注:開始之前,假定你已經成功登錄solr的界面,並創建了core。

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

1、進入解壓好的solr文件夾根目錄下執行以下命令

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自帶的中文分詞器。

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

 

2、進入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,表示 創建索引和搜索時候都生效。不寫默認情況下兩者均生效。
 

 3、添加完畢之后,保存退出並重新啟動 Tomcat服務器,繼續訪問solr。在創建的core中 Analyzer測試中文分詞結果如下。

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

 

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

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

1、首先修改分詞器:

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類型的參數 ,下面會看到他的用處。

 

2、分析器 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類型的參數。

 

3、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的源碼等。

  

  4、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  請根具個人路徑修改配置文件

  

  5、在上問添加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文件如下:

 

6、添加完保存之后,重新訪問 solr,然后在 core的 Analyzer中測試結果如下

 

 因為新增的字段 IK_content,指定的字段類型是IK_cnAnalyzer,該類型使用的是IK中文分詞器,所以使用指定字段或者字段類型,分詞結果是一樣的。

 

7、設置ik的擴展詞庫,

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

 

現在打開配置文件 IKAnalyzer.cfg.xml,

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

 

8、重啟Tomcat服務器之后,繼續分詞查看結果如下

 

很顯然擴展字典生效了,出現了新增的全文搜索、服務器兩個詞組,因此如有需要可以在擴展字典中添加詞組。至於后面重復出現詞組(分詞后的),是因為IK分詞子默認開啟了細粒度的分詞,如果需要開啟智能分詞可以將配置文件中的 useSmart 設置為true即可。 下面是開啟智能分詞后的結果:

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

  總結:

    設置solr的分詞只需要將分詞器的jar包放入solr的依賴文件內,然后在核心core中的managed-schema設置需要的分詞即可。

 文章有很多不足的地方,歡迎大家指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM