?

本章詳細的討論了 Lucene的分析處理過程和幾個Analyzer.

在indexing過程中 要把需要indexing的text分析處理一下, 經過處理和切詞 然后建立index. 而不通的Analyzer有不同的分析規則, 因此在程序中使用Lucene時 選擇正確的Analyzer是很重要的.

1.Using Analyzers

在使用Analyzer以前 先來看看text經過Analyzer分析后的效果吧:

Listing 4.1 Visualizing analyzer effects
Analyzing "The quick brown fox jumped over the lazy dogs"
? WhitespaceAnalyzer:
??? [The] [quick] [brown] [fox] [jumped] [over] [the] [lazy] [dogs]
? SimpleAnalyzer:
??? [the] [quick] [brown] [fox] [jumped] [over] [the] [lazy] [dogs]
? StopAnalyzer:
??? [quick] [brown] [fox] [jumped] [over] [lazy] [dogs]
? StandardAnalyzer:
??? [quick] [brown] [fox] [jumped] [over] [lazy] [dogs]
 

Analyzing "XY&Z Corporation - xyz@example.com"
? WhitespaceAnalyzer:
??? [XY&Z] [Corporation] [-] [xyz@example.com]
? SimpleAnalyzer:
??? [xy] [z] [corporation] [xyz] [example] [com]
? StopAnalyzer:
??? [xy] [z] [corporation] [xyz] [example] [com]
? StandardAnalyzer:
??? [xy&z] [corporation] [xyz@example.com]

上面是在下面我們要提到的一個例子的運行結果. 可以看出不同的Analyzer 是如何來分析text的.在分析The quick brown fox jumped over the lazy dogs 時, WhitespaceAnalyzer和 SimpleAnalyzer只是簡單的把詞分開,建立Term就可以了;而另外兩個Analyzer則去掉了stop word. 而在分析XY&Z Corporation - xyz@example.com 的時候 不同的Analyzer 對待 & 和 - 的方式也是不一樣的 . 現在對Analysis有個感性的了解,下面來看看不同處理階段的分析過程.

I. Indexing Analysis

還記得在ch2 indexing 中 講到 ,在建立index時,使用IndexWriter 在構造IndexWriter時,要使用到Analyser.如下所示:

Analyzer analyzer = new StandardAnalyzer();

IndexWriter writer = new IndexWriter(directory,

analyzer, true);

?

然后就可以使用writer對 document 來indexing了.如下

?

Document doc = new Document();

doc.add(

Field.Text("title", "This is the title"));

doc.add(

Field.UnStored("contents", "...document contents..."));

writer.addDocument(doc);

?

使用的是在構造IndexWriter時 指定的Analyzer. 如果要給一個文檔單獨指定一個Analyzer 可以用下面的一個方法:

?writer.addDocument(doc,analyzer);

II.QueryParser Analysis

? Analysis 是term搜索的關鍵.要確保經過Analyzer分析后的term和被索引的一樣 這樣才可以得到搜索結果.在使用QueryParser parse 用戶輸入的搜索表達式時可以 指定一個Analyzer 如下所示:

Query query = QueryParser.parse(expression, "contents",

analyzer);

?

通過QueryParser的靜態方法實現. 如果使用QueryParser實例, 則可以在構造QueryParser時候 提供一個Analyzer 如下:

QueryParser parser = new QueryParser("contents",

analyzer);

query = parser.parse(expression);

?

QueryParser

analyzes individual pieces of the expression, not the expression as a

whole, which may include operators, parenthesis, and other special expression

syntax to denote range, wildcard, and fuzzy searches.

QueryParser 平等的分析所有的text,她并不知道他們是如何每indxed, 這時如果當搜索一個被索引為Keyword的filed時 就可能會遇到問題.

還有一個問題就是在分析一些包含其他元素的text時該如何處理 ,如 Html xml 文檔, 他們都帶有元素標簽 而這些標簽一般是不索引的.以及如何處理分域(field)索引, 如 Html 有Header 和 Body域 如何分開搜索 這個問題Analyzer現在也不能解決的, 因為在每次Analyzer都處理單個域. 在后面我們在進一步討論該問題.

?

2. Analyzing the Analyzer

要詳細了解Lucene分析文本的過程就要知道Analyzer是如何工作的,下面就來看看Analyzer是怎么工作的吧. Analyzer是各個XXXAnalyzer的基類 ,該類出奇的簡單(比我想象的要簡單多了) 只要一個方法 tokenStream(String fieldName, Reader reader); fieldName 參數對有些Analyzer實現是沒有作用的,如SimpleAnalyzer, 該類的代碼如下:

public final class SimpleAnalyzer extends Analyzer {

? public TokenStream tokenStream(String fieldName, Reader reader) {

??? return new LowerCaseTokenizer(reader);

? }

}

可以看到該類也是出奇的簡單, 只用到了LowerCaseTokenizer; 但LowerCaseTokenizer是干什么的呢? 看看名字就可以猜個差不多啦 ,

該類把Text 中非字母(nonletters)的字符去掉,并把所有Text轉換為小寫.

而返回的

TokenStream 是一個 enumerator-like class ,通過她可以得到連續的 Tokens,當到達末尾時候返回null.

?