lucene索引过程详解

来源:互联网 发布:数据报表什么意思 编辑:程序博客网 时间:2024/06/05 07:14

一、索引是LUCENE最重要的一个过程,通过IndexWriter的addDocument接口,可以将构建的Document加入索引。

二、IndexWriter的addDocument方法首先创建一个DocumentWriter对象,接着为Segment命名,然后调用DocumentWriter的addDocument()方法向索引中增加文档,最后将Segment的信息保存,如果有多个segment则判断是否需要合并,如果需要则合并。一个索引可能有多个segment,每个segment里有许多Document。每个segment的前缀生成方式是将segmentInfos.couter值(当前segment中总共的文档数量)先加1,再转移成36进制,然后在前面加一个下划线就成为了segment的名称。

三、DocumentWriter的addDocument方法完成实际的数据存储工作。

1)第一步,首先初始化一个FieldInfos对象,然后将当前Document传入其中,把所有Field的信息(注意不是内容)写入.fnm文件(在FieldInfos.write完成)。

(A)在写入工作之前使用FieldInfos.add方法将当前的Document加入到fieldInfos对象中。

(B)FieldInfos.write实现:

public void write(Diretory d,String name) throws IOException{

    IndexOutput output=d.createOutput(name);

    try{

//写入fields信息

          write(output);

    }finally{

//关闭输出流

          output.close();

    }

}

 

 

public void write(IndexOutput output) throws IOException{

   //先写入Fields的数量

   output.writerVInt(size());

   //对所有Fields进行循环

   for (int i=0;i<size();i++)  {

        FieldInfo fi=fieldInfo(i);

        byte bits=Ox0;

        if (fi.isIndexed) bits|=IS_INDEXED;

        if (fi.storeTermVector) bits|=STORE_TERMVECTOR;

        if (fi.storePositionWithTermVector) bits|=STORE_POSITIONS_WITH_TERMVECTOR;

        if (fi.storeOffsetWithTermVector) bits|=STORE_OFFSET_WITH_TERMVECTOR;  

        if (fi.omitNorms) bits|=OMIT_NORMS;

        output.writeString(fi.name);

        output.writeByte(bits);

   }

}     

2)第二步,使用fieldWriter.addDocument方法将Document中的各个Field信息写入.fdt文件和.fdx文件。

(A)首先,向.fdx写入当前Document的位置信息

(B)接着,将需要存储的field的数量写入.fdt中

(C)遍历field。

a)如果当前field需要存储,向.fdt中写入field的编号

b)使用位运算来表示当前field的各种属性。向.fdt中写入当前field属性

c)如果field需要压缩,则进行压缩,将压缩后的field数据长度写入.fdt,之后,向.fdt中写入field的值。

d)如果不需要压缩,如果field是二进制类型,则将field数据长度写入.fdt,之后,向.fdt中写入field的值;如果不是二进制类型,直接向.fdt写入field的值

3)第三步,初始化hashtable和其它一些长度数据。

4)调用invertDocument进行文件倒排,有2个主要部分

A)对所有需要加入索引的field进行遍历。对于那些不需要分词的field,就将其整个field的数据做为一个大词条,放入postingTable(一个hashtable)中去(使用adddPostion方法加入名称、值、频率、位置,如果要求还要加上词条向量)。

B)对于需要分词的field,则调用底层分词接口进行分词,然后将每个分出来的词都放入到postingTable中去。

5)第四步,将postingtable进行转化成posting数组进行排序。使所有词条按字典顺序排列

6)第五步,将排列好的词条信息写入.tii和.tis文件,将频率和位置信息.frq和.prx文件

A)lucene索引中对词条的保存并非完整的词条本身,如"smi smith steve" 保存为"smi" "th" "teve"词条片段。

四、索引文件格式

1)segment

每个segment代表lucene的一个完整索引段。在一个索引中,会包含多个segment。每个segment都有统一的前缀,这个前缀是根据当前索引的Document的数量而确立的。一个完整的索引,只有一个segments文件,记录当前索引中所有segment的信息。

2).fnm

.fnm格式的文件中包含了Document中的所有field名称。

3).fdx和.fdt格式

.fdt用于存储具有Store.YES属性的Field的数据。而.fdx类型文件则是一个索引,用于存储Document在.fdt中的位置。

4).tii和.tis格式

.tii用于存储分词后的词条,而.tii是它的索引文件,标明了每个.tis文件中的词条的位置。

五、复合索引格式.cfs

在IndexWriter中有一个属性:useCompoundFile,默认值为True,在初始化完一个IndexWriter对象后,使用setUseCompoundFile(boolean)方法将useCompoundFile的属性值设为True