Lucene doc 文件格式详解

2019-10-11  本文已影响0人  ni_d58f

本文及后面关于Lucene的文章所采用的lucene 版本为8.1.0.

1. 什么是doc文件

doc文件主要用于保存term的倒排表信息,包括docId倒排链及term在docId的term freq信息等。倒排链是Lucene 进行全文检索的核心数据结构,请特别关注这个数据结构


2. doc文件格式

doc文件格式.png

3. 测试代码与结果

请参考Lucene tim文件格式详解 第三部分


4. 范例doc文件内容

doc文件.png

5. doc文件内容分析

5.1 文件头

文件头部分主要内容为标识此文件类型为Lucene50PostingsWriterDoc, 源码部分在Lucene50PostingsWriter的123行,主要内容如下

  1. 3fd7 6c17 固定头MAGIC
  2. 19 为Lucene50PostingsWriterDoc长度25
  3. 4c 7563 656e 6535 3050 6f73 7469 6e67 7357 7269 7465 7244 6f63 25个字节即Lucene50PostingsWriterPos
  4. 00 0000 01 4个字节的BlockTreeTermsReader.VERSION_CURRENT
  5. 836a 556d b951 0bfb cd0f dbfc f298 2299 16个字节的segmentId, 这个是随机生成的
  6. 0a segment suffix 长度 10
  7. 4c75 6365 6e65 3530 5f30 10个字节的segment suffix内容即Lucene50_0

5.2 doc data 部分

开始本部分阅读时,请注意一个在第3部分得到的结果及含义, 现在开始分析该部分内容

下面为term的doc信息。 主要逻辑是: 对于term的doc freq = 1的term来说,doc文件不保存这个term的doc信息,而是在tim文件中保存,doc 文件只保存doc freq > 1的term。在范例中,只有nice的doc freq > 1, 故只保存nice的doc倒排链

...
final int singletonDocID;
   if (state.docFreq == 1) {
     // pulse the singleton docid into the term dictionary, freq is implicitly totalTermFreq
     singletonDocID = docDeltaBuffer[0];
   } else {
     singletonDocID = -1;
     // vInt encode the remaining doc deltas and freqs:
     for(int i=0;i<docBufferUpto;i++) {
       final int docDelta = docDeltaBuffer[i]; //delta编码
       final int freq = freqBuffer[i];
       if (!writeFreqs) {
         docOut.writeVInt(docDelta);
       } else if (freqBuffer[i] == 1) {
         docOut.writeVInt((docDelta<<1)|1);
       } else {
         docOut.writeVInt(docDelta<<1);
         docOut.writeVInt(freq);
       }
     }
   }
...

0<<1, 1 << 1 0 代表doc 0, 实际编码的时候会以128个doc为一个block进行编码, 组内将docId以delta编码。假设现在有doc1, doc2, doc5, doc6, 编码则主1,1,3,1

关于其它term(term freq = 1)的编码方式,请参考tim文件相应的格式内容

5.3 footer区

footer区主要有以下内容


觉得本文有帮助的话,请关注我的简书,一同进步!

上一篇下一篇

猜你喜欢

热点阅读