Apache Lucene(全文檢索引擎)—分詞器

目錄

  返回目錄:http://www.cnblogs.com/hanyinglong/p/5464604.htmlhtml

  本項目Demo已上傳GitHub,歡迎你們fork下載學習:https://github.com/kencery/Lucene_Compass(項目內部有很詳細的註釋)java

1.分詞器的做用

  a. 在建立索引的時候須要用到分詞器,在使用字符串搜索的時候也會用到分詞器,而且這兩個地方要使用同一個分詞器,不然可能會搜索不出來結果。git

  b. 分詞器(Analyzer)的做用是把一段文本中的詞按規則取出所包含的全部詞,對應的是Analyzer類,這是一個抽象類(public abstract class org.apache.lucene.analysis.Analyzer),切分詞的具體規則是由子類實現的,因此對於不一樣的語言規則,要有不一樣的分詞器。github

  c.關於分詞器的詳細運行代碼,請在GitHub上下載,下載地址:https://github.com/kencery/Lucene_Compass/tree/master/Lucene_5.5,對應的分支爲:lucene_five。算法

2.英文分詞器的原理

  a.英文的處理流程爲:輸入文本,詞彙切分,詞彙過濾(去除停用詞),詞幹提取(形態還原)、大寫轉小寫,結果輸出。apache

  b. 何爲形態還原,意思是:去除單詞詞尾的形態變化,將其還原爲詞的原形,這樣作能夠搜索出更多有意義的結果,好比在搜索student的時候,同事也能夠搜索出students的結果。框架

  c. 任何一個分詞法對英文的支持都是還能夠的。學習

3.中文分詞器的原理

  a.中文分詞比較複雜,並無英文分詞那麼簡單,這主要是由於中文的詞與詞之間並非像英文那樣用空格來隔開,測試

由於不是一個字就是一個詞,並且一個詞在另一個地方就可能不是一個詞,如:"咱們是中國人","是中"就不是一個詞,對於中文分詞,一般有三種方式:單字分詞、二分法分詞、詞典分詞。spa

    a.1 單字分詞:就是按照中文一個字一個字的進行分詞,好比:"咱們是中國人",分詞的效果就是"我","們","是","中","國","人",StandardAnalyzer分詞法就是單字分詞。

    a.2 二分法分詞:按照兩個字進行切分,好比:"咱們是中國人",分詞的效果就是:"咱們","們是","是中","中國","國人",CJKAnalyzer分詞法就是二分法分詞

    a.3 詞庫分詞:按照某種算法構造詞,而後去匹配已建好的詞庫集合,若是匹配到就切分出來成爲詞語,一般詞庫分詞被認爲是最好的中文分詞算法,如:"咱們是中國人",分詞的效果就是:"咱們","中國人",極易分詞

MMAnalyzer、庖丁分詞、IkAnalyzer等分詞法就是屬於詞庫分詞。

  b.分詞器還有很大,請你們自行查詢,它們的實現基本一致,都是Analyzer的子類,故而能夠很完美的繼承到Lucene中。

4.停用詞的規則

  a. 有些詞在文本中出現的頻率很是高,可是對文本所攜帶的信息基本不產生影響,例如英文的"a、an、the、of"或中文的"的、了、着、是",以及各類標點符號等,這樣的詞稱爲停用詞,文本通過分詞處理後,停用詞一般會被過濾掉,不會被進行索引,在檢索的時候,用戶的查詢中若是含有停用詞,檢索系統也會將其過濾掉,這是由於用戶輸入哦查詢字符串也要進行分詞處理,排除停用詞能夠礆蕢創建索引的速度,減少索引庫文件的大小。

5.分詞器的使用代碼

  1 package com.lyzj.kencery.unit;
  2 import java.io.StringReader;
  3 import org.apache.lucene.analysis.Analyzer;
  4 import org.apache.lucene.analysis.TokenStream;
  5 import org.apache.lucene.analysis.cjk.CJKAnalyzer;
  6 import org.apache.lucene.analysis.standard.StandardAnalyzer;
  7 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
  8 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
  9 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 10 import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
 11 import org.junit.Test;
 12 import org.wltea.analyzer.lucene.IKAnalyzer;
 13 /**
 14  * 測試分詞器
 15  * 分詞器工做流程
 16  *     1.切分,將須要分詞的內容進行切分紅每一個單詞或者詞語
 17  *     2.去除停用詞,有些詞在文本中出現的頻率很是高,可是對文本所攜帶的信息基本不產生影響,例如英文的「a、an、the、of」,或中文的「的、了、着、是」,以及各類標點符號等,
 18  * 這樣的詞稱爲停用詞(stop word)。文本通過分詞以後,停用詞一般被過濾掉,不會被進行索引。在檢索的時候,用戶的查詢中若是含有停用詞,
 19  * 檢索系統也會將其過濾掉(由於用戶輸入的查詢字符串也要進行分詞處理)。排除停用詞能夠加快創建索引的速度,減少索引庫文件的大小。
 20  *     3.對於英文字母,轉爲小寫,由於搜索的時候不區分大小寫
 21  * @author kencery
 22  *
 23  */
 24 public class AnalyzerTest {
 25 
 26     /**
 27      * StandardAnalyzer分詞法測試,對中文支持不是很好,將中文分詞成1個字(單字分詞)
 28      * @throws Exception 
 29      */
 30     @Test
 31     public void StandardAnalyzerTest() throws Exception{
 32         //英文測試
 33         String text="An IndexWriter creaters and maintains an index.";
 34         Analyzer analyzer=new StandardAnalyzer();
 35         displayTokens(analyzer,text);
 36         //中文測試
 37         String text1="Lucene是全文檢索框架";
 38         displayTokens(analyzer,text1);    
 39     }
 40 
 41      /**
 42       * CJKAnalyzerTest分詞法測試,對中文支持不是很好,將中文分詞成2個字(二分法分詞)
 43       * 
 44       * @throws Exception
 45       */
 46     @Test
 47     public void CJKAnalyzerTest() throws Exception{
 48         //英文測試
 49         String text="An IndexWriter creaters and maintains an index.";
 50         Analyzer analyzer=new CJKAnalyzer();
 51         displayTokens(analyzer,text);
 52         //中文測試
 53         String text1="Lucene是全文檢索框架";
 54         displayTokens(analyzer,text1);    
 55     }
 56 
 57      /**
 58       * IKAnalyzerTest分詞法測試,對中文支持很好,詞庫分詞
 59       * @throws Exception
 60       */
 61     @Test
 62     public void IKAnalyzerTest() throws Exception{
 63         //英文測試
 64         String text="An IndexWriter creaters and maintains an index.";
 65         Analyzer analyzer=new IKAnalyzer();
 66         displayTokens(analyzer,text);
 67         //中文測試
 68         String text1="韓迎龍易淘食的Lucene是全文檢索框架";
 69         displayTokens(analyzer,text1);    
 70     }
 71 
 72     /**
 73      * 使用指定的分詞器對指定的文本進行分詞,並打印出分出的詞,測試分詞法的方法
 74      * 備註說明:這裏注意版本問題,暫無方法解決
 75      * @param analyzer
 76      * @param text
 77      * @throws Exception
 78      */
 79     public static void displayTokens(Analyzer analyzer, String text) throws Exception {
 80         System.out.println("當前使用的分詞器:" + analyzer.getClass().getName());
 81         //分詞流,即將對象分詞後所得的Token在內存中以流的方式存在,也說是說若是在取得Token必須從TokenStream中獲取,而分詞對象能夠是文檔文本,也能夠是查詢文本。
 82         TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
 83         //表示token的首字母和尾字母在原文本中的位置。好比I'm的位置信息就是(0,3),須要注意的是startOffset與endOffset的差值並不必定就是termText.length(),
 84         //由於可能term已經用stemmer或者其餘過濾器處理過;
 85         OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
 86         //這個有點特殊,它表示tokenStream中的當前token與前一個token在實際的原文本中相隔的詞語數量,用於短語查詢。好比: 在tokenStream中[2:a]的前一個token是[1:I'm ],
 87         //它們在原文本中相隔的詞語數是1,則token="a"的PositionIncrementAttribute值爲1;
 88         PositionIncrementAttribute positionIncrementAttribute = tokenStream.addAttribute(PositionIncrementAttribute.class);
 89 
 90         //問題說明:這裏須要使用jdk1.7,若是使用jdk1.8或者jdk1.6則會出現報錯信息
 91         //>>若是你們誰有相應的解決方案,請提交到git上我將會合並或者添加個人QQ咱們互相討論
 92         CharTermAttribute charTermAttribute= tokenStream.addAttribute(CharTermAttribute.class);
 93 
 94         //表示token詞典類別信息,默認爲「Word」,好比I'm就屬於<APOSTROPHE>,有撇號的類型;
 95         TypeAttribute typeAttribute = tokenStream.addAttribute(TypeAttribute.class);
 96         tokenStream.reset();
 97 
 98         int position = 0;
 99         while (tokenStream.incrementToken()) {
100           int increment = positionIncrementAttribute.getPositionIncrement();
101           if(increment > 0) {
102             position = position + increment;
103           }
104           int startOffset = offsetAttribute.startOffset();
105           int endOffset = offsetAttribute.endOffset();
106           String term ="輸出結果爲:"+ charTermAttribute.toString();
107           System.out.println("第"+position+"個分詞,分詞內容是:[" + term + "]" + ",分詞內容的開始結束位置爲:(" + startOffset + "-->" + endOffset + "),類型是:" + typeAttribute.type());
108         }
109         tokenStream.close();
110     }
111 }

 

6. Compass簡單介紹(不建議使用)

  a. 已經不建議使用,由於官方已中止更新,支持的Lucene的最高版本爲2.4,而當前Lucene的版本已經到了5.5。

  b. 由於是學習,因此簡單寫了一個Compass的Demo,下載地址:https://github.com/kencery/Lucene_Compass/tree/master/Compass_2.2,項目內部有詳細的代碼備註。

  c.這裏有一篇別人寫的Compass博客,我的感受很是好,地址:http://yufenfei.iteye.com/blog/1683546

 

   備註:接下來將使用ElasticSearch來作搜索。

相關文章
相關標籤/搜索