lucene使用注意事項

部分信息翻譯自 Apache Lucene FAQ ,請注意標題中 "(翻譯)" 字樣。

IndexWriter.SetUseCompoundFile(true) 有什麼用?

在創建索引庫時,會合並多個 Segments 文件到一個 .cfs 中。此方式有助於減少索引文件數量,減少同時打開的文件數量。

可以使用 CompoundFileReader 查看 .cfs 文件內容。

CompoundFileReader reader = new CompoundFileReader(FSDirectory.GetDirectory("y:\\index", false), "_1oa.cfs");

foreach (string filename in reader.List())
{
    Console.WriteLine(filename);
}


IOException "Too many open files" (翻譯)

原因:
某些操作系統會限制同時打開的文件數量。

解決方法:
1. 使用 IndexWriter's setUseCompoundFile(true) 創建複合文件,減少索引文件數量。
2. 不要將 IndexWriter's mergeFactor 的值設置過大。儘管這能加快索引速度,但會增加同時打開的文件數量。
3. 如果在搜索時發生該錯誤,那麼你最好調用 IndexWriter.Optimize() 優化你的索引庫。
4. 確認你僅創建了一個 IndexSearcher 實例,並且在所有的搜索線程中共用。(原文:"Make sure you only open one IndexSearcher, and share it among all of the threads that are doing searches -- this is safe, and it will minimize the number of files that are open concurently. " 暈~~~,究竟要怎麼做? )

爲什麼搜索不到結果?(翻譯)

可能原因:

1. 搜索字段沒有被索引。
2. 索引庫中的字段沒有分詞存儲,無法和搜索詞語進行局部匹配。
3. 搜索字段不存在。
4. 搜索字段名錯誤,注意字段名稱區分大小寫。建議對字段名進行常量定義。
5. 要搜索的詞語是忽略詞(StopWords)。
6. 索引(IndexWriter)和搜索(IndexSearcher)所使用的 Analyzer 不同。
7. 你所使用的 Analyzer 區分大小寫。比如它使用了 LowerCaseFilter,而你輸入的查詢詞和目標大小寫不同。
8. 你索引的文檔(Document)太大。Lucene 爲避免造成內存不足(OutOfMemory),缺省僅索引前10000個詞語(Term)。可以使用 IndexWriter.setMaxFieldLength() 調整。
9. 確認在搜索前,目標文檔已經被添加到索引庫。
10. 如果你使用了 QueryParser,它可能並沒有按照你所設想的去分析 BooleanQuerySyntax。

如果還不行,那麼:

1. 使用 Query.ToString() 查看究竟搜索了些什麼。
2. 使用 Luke 看看你的索引庫究竟有什麼。

TooManyClauses Exception (翻譯)

使 用 RangeQuery, PrefixQuery, WildcardQuery, FuzzyQuery 等類型時可能會引發該異常。比如我們使用 "ca*" 來搜索 "car" 和 "cars",由於搜索結果文檔(Document)所包含的 Term 超出 Lucene 默認數量限制 (默認1024),則會引發 TooManyClauses 異常。解決方法:

1. 使用 Filter 替換引發異常的 Query,比如使用 RangeFilter 替換 RangeQuery 搜索 DateField 就不會引發 TooManyClauses 異常。你可以使用 ConstantScoreQuery 像 Query 那樣執行 Filter。第一次使用 Filters 時速度要比 Queries 慢一點,但我們可以使用 CachingWrapperFilter 進行緩存。
2. 使用 BooleanQuery.setMaxClauseCount() 加大 Terms 數量,當然這會增加內存佔用。使用 BooleanQuery.setMaxClauseCount(int.MaxValue) 會避開任何限制。
3. 還有一個解決方法是通過縮小字段數據精度來達到減少索引中 Terms 數量的目的。例如僅保存 DateField 中的 "yyyymmddHHMM"(可以使用 Lucene 1.9 版本中的 DateTools)。

通配符

Lucene 支持英文 "?" 和 "*" 通配符,但不能放在單詞首位。

QueryParser 是線程安全的嗎?

不是。

MaxDoc() 和 DocCount()、NumDocs() 有什麼不同?

MaxDocs() 表示索引庫中最大的 Document ID 號,由於中間的某些 Document 可能被刪除,因此不能使用 MaxDocs() 來表示 Document 數量。IndexWriter.DocCount()、IndexReader.NumDocs()、 IndexSearcher.Reader.NumDocs() 都表示索引庫中 Document 數量。

爲什麼同時進行搜索和更新會引發 FileNotFoundException 異常?(翻譯)

可能原因:
1. 某個搜索或更新對象禁用了鎖。
2. 搜索和更新使用了不同的 lockDir。
3. 索引庫被存放在 NFS (or Samba) 文件系統上。

儘管搜索是隻讀操作,但 IndexSeacher 爲了獲取索引文件列表,也必須打開時鎖定索引庫。如果鎖沒有正確設置,那麼它將取回一個錯誤的文件列表(此時 IndexWriter 可能正在添加或優化索引),從而導致該異常發生。

索引文件有大小限制嗎?(翻譯)

某些 32 位操作系統限制每個文件不能大於 2GB。

解決方法:
1. 使用 IndexWriter.setMaxMergeDocs() 減小 MaxMergeDocs 數值。
2. 使用多個索引庫。

什麼是 Segments ?(翻譯)

索引庫中每個索引文件都是由多個 Segments 組成。當你添加一個 Document 到索引庫,那麼就可能會創建一個新的 Segment。你可以使用 Optimize() 來壓縮索引庫以減少 Segments 數量。

write.lock 有什麼用?哪些類會用到它?(翻譯)

write.lock 用來協調索引庫的併發修改處理。
當 IndexWriter 打開索引庫,或者 IndexReader 刪除文檔時都將創建該鎖。

commit.lock 文件有什麼用?哪些類會用到它?(翻譯)

commit.lock 在調整索引庫 segments 文件內容時使用。 IndexReader 和 IndexWriter 都會使用到它。

"Lock obtain timed out." 錯誤。在哪刪除鎖文件?(翻譯)

一 般存放在系統臨時目錄(System.IO.Path.GetTempPath()),也可以在 app.config/web.config 中手工設置。可以手工進行刪除,或者使用 "IndexReader.isLocked"、"IndexReader.unlock" 進行自動判斷和刪除操作。

FSDirectory.cs

public static readonly System.String LOCK_DIR = SupportClass.AppSettings.Get("Lucene.Net.lockDir", System.IO.Path.GetTempPath());


app.config / web.config

<configuration>
    <appSettings>
        <add key="Lucene.Net.lockdir" value="c:\index" />
    </appSettings>
</configuration>


如何更新已經索引的文檔? (翻譯)

你只能先刪除,然後添加更新後的文檔。

使用 IndexWriter.addIndexes(IndexReader[]) 和 IndexWriter.addIndexes(Directory[]) 合併索引庫有什麼不同? (翻譯)

使用 Directory[] 參數所需的文件句柄和內存較小,索引文件僅需打開一次,而使用 IndexReader[] 參數則需要打開所有的索引庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章