2016年6月21日 星期二

lucene analyzer tokenizer(分詞) 的工作記錄

因為最近必須對lucene 的特殊字元進行搜尋(lucene 分詞時
預設是排除特殊字元的, 除了WhiteSpaceAnalyzer), 所以研
究了lucene 分詞的原始碼.

記錄如下:

先說說StandardAnalyzer

StandardAnalyzer extends 自 StopwordAnalyzerBase

當 writer.add(doc) 之後, 會先進入 Analyzer
(所有Analyzer的父類)

然後再根據所選擇的 Analyzer 進入該 Analyzer 執行
CreateComponents 這個函數

CreateComponents 在每一個子類的Analyzer都有不同的實
現方式

例如, 其中StandardAnalyzer 的 CreateComponents 代碼
如下:

@Override
protected TokenStreamComponents createComponents
(final String fieldName, final Reader reader) {
  final StandardTokenizer src =
  new StandardTokenizer(matchVersion, reader);
  src.setMaxTokenLength(maxTokenLength);
  TokenStream tok = new StandardFilter(matchVersion, src);
  tok = new LowerCaseFilter(matchVersion, tok);
  tok = new StopFilter(matchVersion, tok, stopwords);
  return new TokenStreamComponents(src, tok) {
    @Override
    protected void setReader(final Reader reader)
throws IOException {
      src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
      super.setReader(reader);
    }
  };
}

由以上代碼可看出StandardAnalyzer 進行 StandardTokenizer
/StandardFilter/LowerCaseFilter/StopFilter 等程序



再看看WhiteSpaceAnalyzer

  @Override
  protected TokenStreamComponents createComponents
  (final String fieldName,
      final Reader reader) {
    return new TokenStreamComponents(new
WhitespaceTokenizer(matchVersion, reader));
  }

以上可看出 WhiteSpaceAnalyzer, 它的 CreateComponents,
就只有進行WhitespaceTokenizer而己.


以上的StandardTokenizer是進行分詞的程序, 看看它做些什麼
StandardTokenizer中有一個init的函數, 執行
StandardTokenizerImpl 

StandardTokenizerImpl 會實際對全文進行分詞. 這個函數相
當複雜, 很難理解, 我只理解一小部分

其中
private static final char [] ZZ_CMAP = 
zzUnpackCMap(ZZ_CMAP_PACKED);

ZZ_CMAP 存放每一個字元一個值, 用來判斷該字元是分詞時要納入的
正常值,或是不納入的分割字元. 
例如 35是#的ascii內碼
當 ZZ_CMAP[35]=0 時, 代表#在分詞時會被排除
"#abc #def ghi" 分詞後=>abc, def, ghi

當 ZZ_CMAP[35]='~' (十進位為126, 為何是126?不解) 時, 
代表#在分詞時會被納入
"#abc #def ghi" 分詞後=>#abc, #def, ghi

所以想讓#被含在分詞中, 只要 ZZ_CMAP[35]='~' 即可


  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP