IndexWriter.SetUseCompoundFile(true) 有什么用?
在創(chuàng)建索引庫(kù)時(shí),會(huì)合并多個(gè) Segments 文件到一個(gè) .cfs 中。此方式有助于減少索引文件數(shù)量,減少同時(shí)打開的文件數(shù)量。
可以使用 CompoundFileReader 查看 .cfs 文件內(nèi)容。
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" (翻譯)原因:
某些操作系統(tǒng)會(huì)限制同時(shí)打開的文件數(shù)量。
解決方法:
1. 使用 IndexWriter's setUseCompoundFile(true) 創(chuàng)建復(fù)合文件,減少索引文件數(shù)量。
2. 不要將 IndexWriter's mergeFactor 的值設(shè)置過大。盡管這能加快索引速度,但會(huì)增加同時(shí)打開的文件數(shù)量。
3. 如果在搜索時(shí)發(fā)生該錯(cuò)誤,那么你最好調(diào)用 IndexWriter.Optimize() 優(yōu)化你的索引庫(kù)。
4. 確認(rèn)你僅創(chuàng)建了一個(gè) IndexSearcher 實(shí)例,并且在所有的搜索線程中共用。(原文:"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. " 暈~~~,究竟要怎么做? )
為什么搜索不到結(jié)果?(翻譯)可能原因:
1. 搜索字段沒有被索引。
2. 索引庫(kù)中的字段沒有分詞存儲(chǔ),無法和搜索詞語進(jìn)行局部匹配。
3. 搜索字段不存在。
4. 搜索字段名錯(cuò)誤,注意字段名稱區(qū)分大小寫。建議對(duì)字段名進(jìn)行常量定義。
5. 要搜索的詞語是忽略詞(StopWords)。
6. 索引(IndexWriter)和搜索(IndexSearcher)所使用的 Analyzer 不同。
7. 你所使用的 Analyzer 區(qū)分大小寫。比如它使用了 LowerCaseFilter,而你輸入的查詢?cè)~和目標(biāo)大小寫不同。
8. 你索引的文檔(Document)太大。Lucene 為避免造成內(nèi)存不足(OutOfMemory),缺省僅索引前10000個(gè)詞語(Term)??梢允褂?IndexWriter.setMaxFieldLength() 調(diào)整。
9. 確認(rèn)在搜索前,目標(biāo)文檔已經(jīng)被添加到索引庫(kù)。
10. 如果你使用了 QueryParser,它可能并沒有按照你所設(shè)想的去分析 BooleanQuerySyntax。
如果還不行,那么:
1. 使用 Query.ToString() 查看究竟搜索了些什么。
2. 使用 Luke 看看你的索引庫(kù)究竟有什么。
TooManyClauses Exception (翻譯)使用 RangeQuery, PrefixQuery, WildcardQuery, FuzzyQuery 等類型時(shí)可能會(huì)引發(fā)該異常。比如我們使用 "ca*" 來搜索 "car" 和 "cars",由于搜索結(jié)果文檔(Document)所包含的 Term 超出 Lucene 默認(rèn)數(shù)量限制 (默認(rèn)1024),則會(huì)引發(fā) TooManyClauses 異常。解決方法:
1. 使用 Filter 替換引發(fā)異常的 Query,比如使用 RangeFilter 替換 RangeQuery 搜索 DateField 就不會(huì)引發(fā) TooManyClauses 異常。你可以使用 ConstantScoreQuery 像 Query 那樣執(zhí)行 Filter。第一次使用 Filters 時(shí)速度要比 Queries 慢一點(diǎn),但我們可以使用 CachingWrapperFilter 進(jìn)行緩存。
2. 使用 BooleanQuery.setMaxClauseCount() 加大 Terms 數(shù)量,當(dāng)然這會(huì)增加內(nèi)存占用。使用 BooleanQuery.setMaxClauseCount(int.MaxValue) 會(huì)避開任何限制。
3. 還有一個(gè)解決方法是通過縮小字段數(shù)據(jù)精度來達(dá)到減少索引中 Terms 數(shù)量的目的。例如僅保存 DateField 中的 "yyyymmddHHMM"(可以使用 Lucene 1.9 版本中的 DateTools)。
通配符Lucene 支持英文 "?" 和 "*" 通配符,但不能放在單詞首位。
QueryParser 是線程安全的嗎?不是。
MaxDoc() 和 DocCount()、NumDocs() 有什么不同?MaxDocs() 表示索引庫(kù)中最大的 Document ID 號(hào),由于中間的某些 Document 可能被刪除,因此不能使用 MaxDocs() 來表示 Document 數(shù)量。IndexWriter.DocCount()、IndexReader.NumDocs()、 IndexSearcher.Reader.NumDocs() 都表示索引庫(kù)中 Document 數(shù)量。
為什么同時(shí)進(jìn)行搜索和更新會(huì)引發(fā) FileNotFoundException 異常?(翻譯)可能原因:
1. 某個(gè)搜索或更新對(duì)象禁用了鎖。
2. 搜索和更新使用了不同的 lockDir。
3. 索引庫(kù)被存放在 NFS (or Samba) 文件系統(tǒng)上。
盡管搜索是只讀操作,但 IndexSeacher 為了獲取索引文件列表,也必須打開時(shí)鎖定索引庫(kù)。如果鎖沒有正確設(shè)置,那么它將取回一個(gè)錯(cuò)誤的文件列表(此時(shí) IndexWriter 可能正在添加或優(yōu)化索引),從而導(dǎo)致該異常發(fā)生。
索引文件有大小限制嗎?(翻譯)某些 32 位操作系統(tǒng)限制每個(gè)文件不能大于 2GB。
解決方法:
1. 使用 IndexWriter.setMaxMergeDocs() 減小 MaxMergeDocs 數(shù)值。
2. 使用多個(gè)索引庫(kù)。
什么是 Segments ?(翻譯)索引庫(kù)中每個(gè)索引文件都是由多個(gè) Segments 組成。當(dāng)你添加一個(gè) Document 到索引庫(kù),那么就可能會(huì)創(chuàng)建一個(gè)新的 Segment。你可以使用 Optimize() 來壓縮索引庫(kù)以減少 Segments 數(shù)量。
write.lock 有什么用?哪些類會(huì)用到它?(翻譯)write.lock 用來協(xié)調(diào)索引庫(kù)的并發(fā)修改處理。
當(dāng) IndexWriter 打開索引庫(kù),或者 IndexReader 刪除文檔時(shí)都將創(chuàng)建該鎖。
commit.lock 文件有什么用?哪些類會(huì)用到它?(翻譯)commit.lock 在調(diào)整索引庫(kù) segments 文件內(nèi)容時(shí)使用。 IndexReader 和 IndexWriter 都會(huì)使用到它。
"Lock obtain timed out." 錯(cuò)誤。在哪刪除鎖文件?(翻譯)一般存放在系統(tǒng)臨時(shí)目錄(System.IO.Path.GetTempPath()),也可以在 app.config/web.config 中手工設(shè)置??梢允止みM(jìn)行刪除,或者使用 "IndexReader.isLocked"、"IndexReader.unlock" 進(jìn)行自動(dòng)判斷和刪除操作。
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>
如何更新已經(jīng)索引的文檔? (翻譯)你只能先刪除,然后添加更新后的文檔。
使用 IndexWriter.addIndexes(IndexReader[]) 和 IndexWriter.addIndexes(Directory[]) 合并索引庫(kù)有什么不同? (翻譯)使用 Directory[] 參數(shù)所需的文件句柄和內(nèi)存較小,索引文件僅需打開一次,而使用 IndexReader[] 參數(shù)則需要打開所有的索引庫(kù)。