A. 用Lucene 做搜索引擎的時候預處理出錯java.io.IOException: 另一個程序已鎖定文件的一部分,進程無法訪問.
把鎖文件刪除就可以了
B. Lucene需要索引的文本文件太大,怎麼解決
就報錯來看,還沒有用到Lucene就出錯了,意思是只到第一行就虛擬機內存溢出了,可以考慮把源文件進行切割,如把10M的文本切成5個1M的,建議你試一下
給一個可以切分文件的程序,可把它作為預處理的一部分
public static void splitToSmallFiles(File file, String outputpath) throws IOException {
int filePointer = 0;
int MAX_SIZE = 10240000;
BufferedWriter writer = null;
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuffer buffer = new StringBuffer();
String line = reader.readLine();
while (line != null) {
buffer.append(line).append("\\r\
");
if (buffer.toString().getBytes().length >= MAX_SIZE)
{
writer = new BufferedWriter(new FileWriter(outputpath + "output" + filePointer + ".txt"));
writer.write(buffer.toString());
writer.close();
filePointer++;
buffer = new StringBuffer();
}
line = reader.readLine();
}
writer = new BufferedWriter(new FileWriter(outputpath + "output" + filePointer + ".txt"));
writer.write(buffer.toString());
writer.close();
}
C. 搜索引擎Lucene(4):索引的創建過程
創建索引的過程如下:
索引結構如下:
IndexWriter結構:
IndexWriter通過指定存放的目錄(Directory)以及文檔分析器(Analyzer)來構建,direcotry代表索引存儲在哪裡;analyzer表示如何來分析文檔的內容;similarity用來規格化文檔,給文檔算分;IndexWriter類里還有一些SegmentInfos對象用於存儲索引片段信息,以及發生故障回滾等。
添加文檔使用addDocument()方法,刪除文檔使用deleteDocuments(Term)或者deleteDocuments(Query)方法,而且一篇文檔可以使用updateDocument()方法來更新(僅僅是先執行delete在執行add操作而已)。當完成了添加、刪除、更新文檔,應該需要調用close方法。
這些修改會緩存在內存中(buffered in memory),並且定期地(periodically)刷新到(flush)Directory中(在上述方法的調用期間)。一次flush操作會在如下時候觸發(triggered):當從上一次flush操作後有足夠多緩存的delete操作(參見setMaxBufferedDeleteTerms(int)),或者足夠多已添加的文檔(參見setMaxBufferedDocs(int)),無論哪個更快些(whichever is sooner)。對被添加的文檔來說,一次flush會在如下任何一種情況下觸發,文檔的RAM緩存使用率(setRAMBufferSizeMB)或者已添加的文檔數目,預設的RAM最高使用率是16M,為得到索引的最高效率,你需要使用更大的RAM緩存大小。需要注意的是,flush處理僅僅是將IndexWriter中內部緩存的狀態(internal buffered state)移動進索引里去,但是這些改變不會讓IndexReader見到,直到commit()和close()中的任何一個方法被調用時。一次flush可能觸發一個或更多的片斷合並(segmentmerges),這時會啟動一個後台的線程來處理,所以不會中斷addDocument的調用,請參考MergeScheler。
一個IndexReader或者IndexSearcher只會看到索引在它打開的當時的狀態。任何在索引被打開之後提交到索引中的commit信息,在它被重新打開之前都不會見到。
DocumentsWriter結構:
DocumentsWriter 是由IndexWriter 調用來負責處理多個文檔的類,它通過與Directory 類及Analyzer 類、Scorer 類等將文檔內容提取出來,並分解成一組term列表再生成一個單一的segment 所需要的數據文件,如term頻率、term 位置、term 向量等索引文件,以便SegmentMerger 將它合並到統一的segment 中去。
該類可接收多個添加的文檔,並且直接寫成一個單獨的segment 文件。這比為每一個文檔創建一個segment(使用DocumentWriter)以及對那些segments 執行合作處理更有效率。
每一個添加的文檔都被傳遞給DocConsumer類,它處理該文檔並且與索引鏈表中(indexing chain)其它的consumers相互發生作用(interacts with)。確定的consumers,就像StoredFieldWriter和TermVectorsTermsWriter,提取一個文檔的摘要(digest),並且馬上把位元組寫入「文檔存儲」文件(比如它們不為每一個文檔消耗(consume)內存RAM,除了當它們正在處理文檔的時候)。
其它的consumers,比如FreqProxTermsWriter和NormsWriter,會緩存位元組在內存中,只有當一個新的segment製造出的時候才會flush到磁碟中。
一旦使用完我們分配的RAM緩存,或者已添加的文檔數目足夠多的時候(這時候是根據添加的文檔數目而不是RAM的使用率來確定是否flush),我們將創建一個真實的segment,並將它寫入Directory中去。
索引創建的調用過程:
一個Directory對象是一系列統一的文件列表(a flat list of files)。文件可以在它們被創建的時候一次寫入,一旦文件被創建,它再次打開後只能用於讀取(read)或者刪除(delete)操作。並且同時在讀取和寫入的時候允許隨機訪問。
FSDirectory類直接實現Directory抽象類為一個包含文件的目錄。目錄鎖的實現使用預設的SimpleFSLockFactory,但是可以通過兩種方式修改,即給getLockFactory()傳入一個LockFactory實例,或者通過調用setLockFactory()方法明確制定LockFactory類。
目錄將被緩存(cache)起來,對一個指定的符合規定的路徑(canonical path)來說,同樣的FSDirectory實例通常通過getDirectory()方法返回。這使得同步機制(synchronization)能對目錄起作用。
RAMDirectory類是一個駐留內存的(memory-resident)Directory抽象類的實現。目錄鎖的實現使用預設的SingleInstanceLockFactory,但是可以通過setLockFactory()方法修改。
IndexInput類是一個為了從一個目錄(Directory)中讀取文件的抽象基類,是一個隨機訪問(random-access)的輸入流(input stream),用於所有Lucene讀取Index的操作。BufferedIndexInput是一個實現了帶緩沖的IndexInput的基礎實現。
IndexOutput類是一個為了寫入文件到一個目錄(Directory)中的抽象基類,是一個隨機訪問(random-access)的輸出流(output stream),用於所有Lucene寫入Index的操作。BufferedIndexOutput是一個實現了帶緩沖的IndexOutput的基礎實現。RAMOuputStream是一個內存駐留(memory-resident)的IndexOutput的實現類。
域索引選項通過倒排索引來控制文本是否可被搜索。
當lucene建立起倒排索引後,默認情況下它會保存所有必要的信息以實施Vector Space Model。該Model需要計算文檔中出現的Term數,以及它們出現的文職(這是必要的,比如通過片語搜索時用到)。但有時候這些域只是在布爾搜索時用到,他們並不為相關評分做貢獻,一個常見的例子是,域只是被用作過濾,如許可權過濾和日期過濾。在這種情況下,可以通過調用Field.setOmitTermFreqAndPositions(true)方法讓lucene跳過對改選項的出現頻率和出現位置的索引。該方法可以節省一些索引在磁碟上的儲存空間,還可以加速搜索和過濾過程,但會悄悄阻止需要位置信息的搜索,如阻止PhraseQuery和SpanQuery類的運行。
域存儲選項是用來確定是否需要存儲域的真實值,以便後續搜索時能回復這個值。
lucene支持想一個域中寫入多個不同的值。
這種處理方式是完全可以接受並鼓勵使用的,因為這是邏輯上具有多個域值的域的自然表示方式。在lucene內部,只要文檔中出現同名的多域值,倒排索引和項向量都會在邏輯上將這些語匯單元附加進去,具體順序由添加該域的順序決定。
文檔和域的加權操作可以在索引期間完成。而搜索期間的加權操作會更加動態化,因為每次搜索都可以根據不同的加權因子獨立選擇加權或不加權,但這個策略也可能多消耗一些CPU效率。搜索期間的動態加權可以更靈活控制。
默認情況下,所有文檔的加權因子都是1.0,通過改變文檔的加權因子,就可以影響文檔在索引中的重要程度。調整加權操作的API為:setBoost(float);
同文檔加權一樣,可以對進行加權操作。文檔加權時,lucene內部會採用同一加權因子來對該文檔中的域進行加權。域加權API:Field.setBoost(fliat)。
Analyzer類構建用於分析文本的TokenStream對象,因此(thus)它表示(represent)用於從文本中分解(extract)出組成索引的terms的一個規則器(policy)。典型的(typical)實現首先創建一個Tokenizer,它將那些從Reader對象中讀取字元流(stream of characters)打碎為(break into)原始的Tokens(raw Tokens)。然後一個或更多的TokenFilters可以應用在這個Tokenizer的輸出上。警告:你必須在你的子類(subclass)中覆寫(override)定義在這個類中的其中一個方法,否則的話Analyzer將會進入一個無限循環(infinite loop)中。
StandardAnalyzer:
StandardAnalyzer類是使用一個English的stop words列表來進行tokenize分解出文本中word,使用StandardTokenizer類分解詞,再加上StandardFilter以及LowerCaseFilter以及StopFilter這些過濾器進行處理的這樣一個Analyzer類的實現。
D. 為什麼我的Lucene的索引被鎖定
被IIS鎖定時什麼情況呢?
不具有讀寫許可權? 還是有一個?.lock文件 。 如果創建索引的時候異常中斷,可以嘗試刪除lock文件或者重新生成。並賦予該文件夾正確的許可權信息。
E. 在Lucene中刪除索引,使用writer.optimize();//優化操作使刪除生效,可是這一句老是有錯,求大神指教。
IndexReader提供了兩種方法:
reader.DeleteDocument(int
docNum)
reader.DeleteDocuments(Term term)
前者是根據文檔的編號來刪除該文檔,docNum是該文檔進回入索引時Lucene的編號,答是按照順序編的;後者是刪除滿足某一個條件的多個文檔。
在執行了DeleteDocument或者DeleteDocuments方法後,系統會生成一個*.del的文件,該文件中記錄了刪除的文檔,但並未從物理上刪除這些文檔。此時,這些文檔是受保護的,當使用Document
doc = reader.Document(i)來訪問這些受保護的文檔時,Lucene會報「Attempt to access a deleted
document」異常。如果一次需要刪除多個文檔時,可以用兩種方法來解決:
1. 刪除一個文檔後,用IndexWriter的Optimize方法來優化索引,這樣我們就可以繼續刪除另一個文檔。
2.
先掃描整個索引文件,記錄下需要刪除的文檔在索引中的編號。
F. 用lucene建立索引時,當第二次創建時,還在同一個目錄下,那麼之前的索引會被刪除嗎
你用Lucene建立索引的時候IndexWriter writer = new IndexWriter(indexdir,new StandardAnalyzer(), true);
第三個參數當為TRUE時是會刪除同一個目錄下的索引的,這是在回初次創建答索引時使用
以後每次增量索引直接設置為FALSE即可,這樣直接將後面新建立的索引添加到索引文件中,不會覆蓋原來建立的索引。
當刪除索引時我們可以找到對應的索引ID,然後刪除索引,將刪除掉索引文件中的該條記錄,同時在同目錄下生成一個刪除索引的記錄問價,為-DEL文件,便於後面恢復刪除的索引。
以上解答希望你能理解,建個簡單的索引試試就可以知道的