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

来源:互联网 发布:voip服务器软件 编辑:程序博客网 时间:2024/05/18 03:34

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 termsTCHAR* test2 = _T("computer in a computer lab"); //5 termsTCHAR* test3 = _T("a chocolate lab grows old"); //5 termsTCHAR* test4 = _T("eating chocolate with a chocolate lab in an old chocolate colored computer lab"); //13 termsDocument 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();

索引合并流程图如下:

索引合并也是一个比较复杂过程,主要流程如下:

索引文件总体结构:


0 0