全文檢索Solr集成HanLP中文分詞

 

之前發佈過HanLP的Lucene插件,後來不少人跟我說其實Solr更流行(反正我是以爲既然Solr是Lucene的子項目,那麼稍微改改配置就能支持Solr),因而就抽空作了個Solr插件出來,開源在Github上,歡迎改進。java

HanLP中文分詞solr插件支持Solr5.x,兼容Lucene5.x。git

圖1程序員

快速上手github

一、將hanlp-portable.jarhanlp-solr-plugin.jar共兩個jar放入${webapp}/WEB-INF/lib下web

二、修改solr core的配置文件${core}/conf/schema.xml:瀏覽器

  <fieldType name="text_cn" class="solr.TextField">app

      <analyzer type="index">webapp

          <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>工具

      </analyzer>post

      <analyzer type="query">

          <!-- 切記不要在query中開啓index模式 -->

          <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="false"/>

      </analyzer>

  </fieldType>

  <!-- 業務系統中須要分詞的字段都須要指定type爲text_cn -->

  <field name="my_field1" type="text_cn" indexed="true" stored="true"/>

  <field name="my_field2" type="text_cn" indexed="true" stored="true"/>

Solr5中文分詞器詳細配置

對於新手來講,上面的兩步可能太簡略了,不如看看下面的step by step。本教程使用Solr5.2.1,理論上兼容solr5.x。

放置jar

將上述兩個jar放到solr-5.2.1/server/solr-webapp/webapp/WEB-INF/lib目錄下。若是你想自定義詞典等數據,將hanlp.properties放到solr-5.2.1/server/resources,該目錄也是log4j.properties等配置文件的放置位置。HanLP文檔一直在說「將配置文件放到resources目錄下」,指的就是這個意思。做爲Java程序員,這是基本常識。

啓動solr

首先在solr-5.2.1\bin目錄下啓動solr:

1.solr start -f

用瀏覽器打開http://localhost:8983/solr/#/,看到以下頁面說明一切正常:

圖2

建立core

在solr-5.2.1\server\solr下新建一個目錄,取個名字好比叫one,將示例配置文件solr-5.2.1\server\solr\configsets\sample_techproducts_configs\conf拷貝過來,接着修改schema.xml中的默認域type,搜索

 1.   <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">

 2.       ...

 3.   </fieldType>

 

替換爲

  1. <!-- 默認文本類型: 指定使用HanLP分詞器,同時開啓索引模式。
  2. 經過solr自帶的停用詞過濾器,使用"stopwords.txt"(默認空白)過濾。
  3. 在搜索的時候,還支持solr自帶的同義詞詞典。-->
  4. <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  5. <analyzer type="index">
  6. <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>
  7. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
  8. <!-- 取消註釋能夠啓用索引期間的同義詞詞典
  9. <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
  10. -->
  11. <filter class="solr.LowerCaseFilterFactory"/>
  12. </analyzer>
  13. <analyzer type="query">
  14. <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>
  15. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
  16. <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
  17. <filter class="solr.LowerCaseFilterFactory"/>
  18. </analyzer>
  19. </fieldType>

 

意思是默認文本字段類型啓用HanLP分詞器,text_general還開啓了solr默認的各類filter。

solr容許爲不一樣的字段指定不一樣的分詞器,因爲絕大部分字段都是text_general類型的,能夠說這種作法比較適合新手。若是你是solr老手的話,你可能會更喜歡單獨爲不一樣的字段指定不一樣的分詞器及其餘配置。若是你的業務系統中有其餘字段,好比location,summary之類,也須要一一指定其type="text_general"。切記,不然這些字段仍舊是solr默認分詞器,會形成這些字段「搜索不到」。

另外,切記不要在query中開啓indexMode,不然會影響PhaseQuery。indexMode只需在index中開啓一遍便可,要否則它怎麼叫indexMode呢。

若是你不須要solr提供的停用詞、同義詞等filter,以下配置可能更適合你:

1. <fieldType name="text_cn" class="solr.TextField">

2.      <analyzer type="index">

3.          <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>

4.      </analyzer>

5.      <analyzer type="query">

6.          <!-- 切記不要在query中開啓index模式 -->

7.          <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="false"/>

8.      </analyzer>

9.  </fieldType>

10.  <!-- 業務系統中須要分詞的字段都須要指定type爲text_cn -->

11.  <field name="my_field1" type="text_cn" indexed="true" stored="true"/>

12.  <field name="my_field2" type="text_cn" indexed="true" stored="true"/>

完成了以後在solr的管理界面導入這個core one:

3

接着就能在下拉列表中看到這個core了:

4

上傳測試文檔

修改好了,就能夠拿一些測試文檔來試試效果了。hanlp-solr-plugin代碼庫中的src/test/resources下有個測試文檔集合documents.csv,其內容以下:

  1. id,title
  2. 1,你好世界
  3. 2,商品和服務
  4. 3,和服的價格是每鎊15便士
  5. 4,服務大衆
  6. 5,hanlp工做正常

 

表明着id從1到5共五個文檔,接下來複制solr-5.2.1\example\exampledocs下的上傳工具post.jar到resources目錄,利用以下命令行將數據導入:

  1. java -Dc=one -Dtype=application/csv -jar post.jar *.csv

 

Windows用戶的話直接雙擊該目錄下的upload.cmd便可,Linux用戶運行upload.sh。

正常狀況下輸出以下結果:

1. SimplePostTool version 5.0.0

2. Posting files to [base] url http://localhost:8983/solr/one/update using content-

3. type application/csv...

4. POSTing file documents.csv to [base]

5. 1 files indexed.

6. COMMITting Solr index changes to http://localhost:8983/solr/one/update...

7. Time spent: 0:00:00.059

8. 請按任意鍵繼續. . .

 

同時刷新一下core one的Overview,的確看到了5篇文檔:

5

搜索文檔

是時候看看HanLP分詞的效果了,點擊左側面板的Query,輸入「和服」試試:

6

發現精確地查到了「和服的價格是每鎊15便士」,而不是「商品和服務」這種錯誤文檔:

7

這說明HanLP工做良好。

要知道,很多中文分詞器眉毛鬍子一把抓地命中「商品和服務」這種錯誤文檔,下降了查準率,拉低了用戶體驗,跟原始的MySQL LIKE有何區別?

索引模式的功能

索引模式能夠對長詞進行全切分,獲得其中蘊含的全部詞彙。好比「中醫藥大學附屬醫院」在HanLP索引分詞模式下的切分結果爲:

  1. 中0 醫1 藥2 大3 學4 附5 屬6 醫7 院8 
  2. [0:3 1] 中醫藥/n
  3. [0:2 1] 中醫/n
  4. [1:3 1] 醫藥/n
  5. [3:5 1] 大學/n
  6. [5:9 1] 附屬醫院/nt
  7. [5:7 1] 附屬/vn
  8. [7:9 1] 醫院/n

開啓indexMode後,不管用戶搜索「中醫」「中醫藥」仍是「醫藥」,都會搜索到「中醫藥大學附屬醫院」:

8

高級配置

目前本插件支持以下基於schema.xml的配置:

9

對於更高級的配置,HanLP分詞器主要經過class path下的hanlp.properties進行配置,請閱讀HanLP天然語言處理包文檔以瞭解更多相關配置,如:

1.停用詞

2.用戶詞典

3.詞性標註

4.……

代碼調用

在Query改寫的時候,能夠利用HanLPAnalyzer分詞結果中的詞性等屬性,如

  1. String text = "中華人民共和國很遼闊";
  2. for (int i = 0; i < text.length(); ++i)
  3. {
  4.     System.out.print(text.charAt(i) + "" + i + " ");
  5. }
  6. System.out.println();
  7. Analyzer analyzer = new HanLPAnalyzer();
  8. TokenStream tokenStream = analyzer.tokenStream("field", text);
  9. tokenStream.reset();
  10. while (tokenStream.incrementToken())
  11. {
  12.     CharTermAttribute attribute = tokenStream.getAttribute(CharTermAttribute.class);
  13.     // 偏移量
  14.     OffsetAttribute offsetAtt = tokenStream.getAttribute(OffsetAttribute.class);
  15.     // 距離
  16.     PositionIncrementAttribute positionAttr = kenStream.getAttribute(PositionIncrementAttribute.class);
  17.     // 詞性
  18.     TypeAttribute typeAttr = tokenStream.getAttribute(TypeAttribute.class);
  19.     System.out.printf("[%d:%d %d] %s/%s\n", offsetAtt.startOffset(), offsetAtt.endOffset(), positionAttr.getPositionIncrement(), attribute, typeAttr.type());
  20. }

 

在另外一些場景,支持以自定義的分詞器(好比開啓了命名實體識別的分詞器、繁體中文分詞器、CRF分詞器等)構造HanLPTokenizer,好比:

  1. tokenizer = new HanLPTokenizer(HanLP.newSegment()
  2.                     .enableJapaneseNameRecognize(true)
  3.                     .enableIndexMode(true), null, false);
  4. tokenizer.setReader(new StringReader("林志玲亮相網友:肯定不是波多野結衣?"));
  5. ...

反饋

技術問題請在Github上發issue ,你們一塊兒討論,也方便集中管理。博客留言、微博私信、郵件不受理任何HanLP相關的問題,謝謝合做!

反饋問題的時候請必定附上版本號、觸發代碼、輸入輸出,不然沒法處理。

版權

Apache License Version 2.0

轉載子碼農場

相關文章
相關標籤/搜索