拆解Cluene系列(8)——建立索引的流程

Cluene在建立索引時,主要經歷以下幾個步驟:

  1. 利用Analyzer對content進行處理,構成一個個token.
  2. 根據token,構建倒排索引,將索引寫到文件(一個索引包含多個不同類型的文件)。
  3. 如果有可能,將多個較小的索引文件合併成一個較大的索引文件。
  4. 重複1-3,直到所有文章處理完畢。

其序列圖如下:

   可以看到,整個過程是一個大的loop,可以反覆地添加document,每個doc又包含多個字段和相應的content. 可以看到主要用到類是IndexWriter類和DocumentWriter類,在流程的前半段,主要使用DocumentWriter,Lucene自帶的測試例子是從IndexWriter作爲出發點,並且看不到產生的索引文件,默認生成的索引文件都是在內存中,只是最終合併成一個物理文件放到磁盤上,爲了學習和理解DocumentWriter,我使用的如下的測試例子:

void testDocWriter2(CuTest *tc)
{
	SimpleAnalyzer a;
	RAMDirectory dir;
	Similarity *sim = CL_NS(search)::Similarity::getDefault();
	FSDirectory *fs= FSDirectory::getDirectory("E:/xxxx",true);
	int maxFieldCount=10000;
	DocumentWriter docW(fs,&a,sim,maxFieldCount);

	TCHAR* test1 = _T("eating chocolate in a computer lab"); //6 terms
	TCHAR* test2 = _T("computer in a computer lab"); //5 terms
	TCHAR* test3 = _T("a chocolate lab grows old"); //5 terms
	TCHAR* test4 = _T("eating chocolate with a chocolate lab in an old chocolate colored computer lab"); //13 terms

	Document testDoc1;
	testDoc1.add(*Field::Text(_T("title"),test1,true));
	testDoc1.add(*Field::Text(_T("content"),test2,true));
	docW.addDocument(newSegmentName(),&testDoc1);
	Document testDoc2;
	testDoc2.add(*Field::Text(_T("title"),test3,false));
	docW.addDocument(newSegmentName(),&testDoc2);
}

這裏添加了兩個doc,其中一個doc,含有兩個field,另一個doc,含有一個field。在創建索引時,Lucene會爲每個doc起一個新的名字(這個名字是永不重複的,並且是不可改變的,即使這個doc被合併後,其name也是不變的)。索引產生的文件都是以這個名字命名,只是擴展名不同。下面詳細講解lucene創建索引的過程:

1-4):準備階段,構建索引數據。

5-6):生成索引信息文件。索引信息文件主要存放fieldinfo信息,包括Field的Name,Field的屬性(是否存儲,是否索引)。是最主要的文件。所有其他的文件都依賴於此文件的內容,這個文件要最新生成,在讀取索引時,也要首先讀取這個文件。

7-8)生成xxx.fdt和xxx.fdx,記錄了索引對應的內容,這樣,在查找時,如果找到了包含索引的文檔,可以把文檔還原出來。

9-13) 生成postingTable並寫入文件的過程,其中 10:InvertDocument()是在構建倒排索引,12.將生成的倒排索引進行排序,用到了快速排序。

         這個過程中,產生的文件如下:

        1. xxx.tii:Term索引文件 xxx.tis Term數據文件

             由於Term數據文件中含有大量的Term,爲了加快查找速度。對Term數據文件,建立了二級甚至三級 “索引”。這就是tii文件,其中用到了跳躍表技術。

        2. xxx.freq 和xxx.prox, 記錄了term在doc(確切地講,是field)出現的次數和位置。這裏用到“差值規則和或然跟隨規則".

        3. xxx.tvf xxx.tvx xxx.tvd 這幾個文件並不是一定會生成的,只有設置了storeTermVector屬性,纔會生成這幾個文件,主要記錄了term在文檔中的次數。

 

14). 記錄每個每個字段的權重,默認等於document的權重。

15). 進入建立索引的後半程,當產生的索引文件達到一定個數時,程序會自動將幾個索引文件合併成一個較大的索引文件。主要包含以下幾個部分:

  1. 合併域:mergeFields()
  2. 合併詞典和倒排表:mergeTerms();
  3. 合併標準化因子:mergeNorms();
  4. 合併詞向量:mergeVectors();

索引合併流程圖如下:

索引合併也是一個比較複雜過程,主要流程如下:

索引文件總體結構:


發佈了105 篇原創文章 · 獲贊 35 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章