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

    xiaoxiao2024-05-07  7

    Cluene在建立索引时,主要经历以下几个步骤:

    利用Analyzer对content进行处理,构成一个个token.根据token,构建倒排索引,将索引写到文件(一个索引包含多个不同类型的文件)。如果有可能,将多个较小的索引文件合并成一个较大的索引文件。重复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). 进入建立索引的后半程,当产生的索引文件达到一定个数时,程序会自动将几个索引文件合并成一个较大的索引文件。主要包含以下几个部分:

    合并域:mergeFields() 合并词典和倒排表:mergeTerms(); 合并标准化因子:mergeNorms();合并词向量:mergeVectors();

    索引合并流程图如下:

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

    索引文件总体结构:

    转载请注明原文地址: https://ju.6miu.com/read-1288329.html
    最新回复(0)