本章詳細的討論了 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 awhole, 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.?