DocValues 查找


举个例子,构造如下场景(代码:https://github.com/debuger6/lucene/blob/branch-v9.5.0/lucene/demo/src/java/org/apache/lucene/own/demo/docvalue/NumericDocValuesFieldDemo.java#L76):

共10个 block,block0 不存文档号,缺失。后面 9 个 block,每个 block 的第 20000 个文档号缺失,因此,每个 block 的文档数为 65535,那么 IndexedDISI 的结构大致如下:

image-20230524000151474

这里以最复杂的情况即稠密度为 dense 举例,假设查找文档号 3 * (1 « 16) + 65530 ,即查找第 3 个 block 中第 65530 个文档,那么步骤如下:

  1. 找到 target 所属的 block3

  2. 通过 JumpTable 找到 block3 对应的 index (第一个有效文档号的段内偏移,即 131070)

  3. 通过 JumpTable 找到 block3 对应的 offset (dvd 文件偏移)

  4. 定位到 block3

  5. 读取 block3 头部,根据 block id 计算 block 第一个文档号(block_id « 16)

  6. 读取 block 头部,获取 ranks

  7. 定位到 target 所在的 word(target word)

  8. 通过 ranks 加速统计 block 内当前 word 到 target word 的文档数

  9. 根据下面代码可以判断 target 是否存在以及算出 target 的段内偏移

    long leftBits = disi.word >>> target; // 此时 word 为 target word,最低位的 bit 表示 target 是否存在
    disi.index = disi.numberOfOnes - Long.bitCount(leftBits); // 计算 target doc 的段内偏移
    return (leftBits & 1L) != 0; // 最低位为 1 说明 target doc 存在
    

上面通过 IndexDISI 找到了 target 在段内的偏移 disi.index(当然,如果文档不存在,下面的步骤就不用做了),