`
chengqianl
  • 浏览: 53218 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

DefaultSkipListReader查找docId

阅读更多
DefaultSkipListReader查找docId
MultiLevelSkipListReader
public MultiLevelSkipListReader(IndexInput skipStream, int maxSkipLevels, int skipInterval) {
/**每个层的文件文件的IndexInput读取对象,是通过定位到每个文件的相对应的skiptable的位置层的位置,clone下就得到新的IndexInput 对象了
**/
this.skipStream = new IndexInput[maxSkipLevels];
/**
Skiplist每次的
**/
this.skipPointer = new long[maxSkipLevels];
//
this.childPointer = new long[maxSkipLevels];
// 当前层相对原始层跳过的元素个数
this.numSkipped = new int[maxSkipLevels];
// 跳表有多少层
this.maxNumberOfSkipLevels = maxSkipLevels;
// 每层相对于原始层跳表的间隔的元素个数
this.skipInterval = new int[maxSkipLevels];

    this.skipStream [0]= skipStream;
    this.inputIsBuffered = (skipStream instanceof BufferedIndexInput);
this.skipInterval[0] = skipInterval;
// 由于skipInterval 是已知的,所以每层的间隔就可以计算出来
    for (int i = 1; i < maxSkipLevels; i++) {
      // cache skip intervals
      this.skipInterval[i] = this.skipInterval[i - 1] * skipInterval;
}
//记录当前层的docId的
    skipDoc = new int[maxSkipLevels];
  }


skipTo(int target)
扫描skiplist返回不小于某个docId的前面的那个skipdata所比较的doc的数目
int skipTo(int target) throws IOException {
    if (!haveSkipped) {
      // first time, load skip levels
      loadSkipLevels();
      haveSkipped = true;
    }
 
// skipDoc 记录是当前level遍历到的docId,从最低层向最高层比较,直到找到targt大//于某个level的docId
    // walk up the levels until highest level is found that has a skip
    // for this target
    int level = 0;
    while (level < numberOfSkipLevels - 1 && target > skipDoc[level + 1]) {
      level++;
    }   
// 查找
    while (level >= 0) {
      if (target > skipDoc[level]) {// 如果target大于level上的docId,读取//下一个skiplist实体skipdata,直到找到大于这个target的docId
        if (!loadNextSkip(level)) {
          continue;
        }
      } else {
        // no more skips on this level, go down one level
        if (level > 0 && lastChildPointer > skipStream[level - 1].getFilePointer()) {
          seekChild(level - 1);
        }
        level--;
      }
    }
    //
    return numSkipped[0] - skipInterval[0] - 1;
  }


loadSkipLevels()
加载level信息,
/** Loads the skip levels  */
  private void loadSkipLevels() throws IOException {

/**由包含这个term的document的数目计算skiptable的层数,如果超过maxNumberOfSkipLevels则为maxNumberOfSkipLevels**/

    numberOfSkipLevels = docCount == 0 ? 0 : (int) Math.floor(Math.log(docCount) / Math.log(skipInterval[0]));
    if (numberOfSkipLevels > maxNumberOfSkipLevels) {
      numberOfSkipLevels = maxNumberOfSkipLevels;
}

//Seek到skipPointer[0]的位置,也就是也就是,在frg文件里面skipdata起始位置如果图2

    skipStream[0].seek(skipPointer[0]);
   
/** 标识读取到内存中的skiptable中level的数目**/  
int toBuffer = numberOfLevelsToBuffer;
    //
for (int i = numberOfSkipLevels - 1; i > 0; i--) {
//  skiptable的层的长度,如后面图1标示
      // the length of the current level
      long length = skipStream[0].readVLong();
      // 当前层的起始偏移量
      // the start pointer of the current level
      skipPointer[i] = skipStream[0].getFilePointer();
      if (toBuffer > 0) {
// 将文件数据读入到内存,定位到下一个level的起始位置
        // buffer this level
        skipStream[i] = new SkipBuffer(skipStream[0], (int) length);
        toBuffer--;
      } else {
// 克隆这个IndexInput,为了每个level的读取
        // clone this stream, it is already at the start of the current level
        skipStream[i] = (IndexInput) skipStream[0].clone();
        if (inputIsBuffered && length < BufferedIndexInput.BUFFER_SIZE) {
          ((BufferedIndexInput) skipStream[i]).setBufferSize((int) length);
        }
        //定位到下一个level的起始位置
        // move base stream beyond the current level
        skipStream[0].seek(skipStream[0].getFilePointer() + length);
      }
    }
  
    // use base stream for the lowest level
    skipPointer[0] = skipStream[0].getFilePointer();
  }









loadNextSkip
private boolean loadNextSkip(int level) throws IOException {
/**
设置最后访问层的docId和下个节点的位置
**/
    // we have to skip, the target document is greater than the current
    // skip list entry       
    setLastSkipData(level);
    // 记录跳过的元素的个数,例如跳表的间隔为16,则第0层的第一个元素相对于原数据,跳过了16个元素,第1层相对于第0层跳过了16 个元素,第1层相对于原始层跳过了16*16 个元素,这个地方记录的是相对原始层跳过的元素的个数
    numSkipped[level] += skipInterval[level];
      // 判断某层跳过的document的数目是否大于最大文档数目
    if (numSkipped[level] > docCount) {
      // this skip list is exhausted
      skipDoc[level] = Integer.MAX_VALUE;
      if (numberOfSkipLevels > level) numberOfSkipLevels = level;
      return false;
    }
// 读取跳表中实体的值,返回的docId和前面一个实体的docId的差值,所以正确的值应//该是,返回值加上前面的差值skipDoc[],这个数组记录的是当前level的移动到的实体的//docId
    // read next skip entry
    skipDoc[level] += readSkipData(level, skipStream[level]);
   
if (level != 0) {
// 计算下一个level的起始位置,也就是本层的skipdata在下个层的位置
      // read the child pointer if we are not on the leaf level
      childPointer[level] = skipStream[level].readVLong() + skipPointer[level - 1];
    }
   
    return true;

  }




readSkipData
//读取一个跳表中的实体
protected int readSkipData(int level, IndexInput skipStream) throws IOException {
    int delta;// docId 运营delDa规则存储的
    if (currentFieldStoresPayloads) {
      // the current field stores payloads.
      // if the doc delta is odd then we have
      // to read the current payload length
      // because it differs from the length of the
      // previous payload
      delta = skipStream.readVInt();
      if ((delta & 1) != 0) {
        payloadLength[level] = skipStream.readVInt();
      }
      delta >>>= 1;
    } else {
      delta = skipStream.readVInt();
}
//文档号对应的倒排表中的节点在frq
//中的偏移量,文档号对应的倒排表中的节点在prx中的偏移量。
    freqPointer[level] += skipStream.readVInt();
    proxPointer[level] += skipStream.readVInt();
   
    return delta;
  }

next()
public boolean next() throws IOException {
    while (true) {
      if (count == df)
        return false;
// 读取下一个docId
      final int docCode = freqStream.readVInt();
     
      if (currentFieldOmitTermFreqAndPositions) {
        doc += docCode;
        freq = 1;
      } else {
// 由于使用了DocDelta[, Freq?],规则,所以读到的docId,向左移一位得到和前面skipdata的docId的差值,加上前面的docId的值就是实际的docId的值,由于frg等于1,则docCode 的最后一位是 1,说明frg等于1,不用往后读取frg的值了。

        doc += docCode >>> 1;       // shift off low bit
        if ((docCode & 1) != 0)       // if low bit is set
          freq = 1;         // freq is one
        else
          freq = freqStream.readVInt();     // else read freq
      }
     
      count++;

// 查看docId是否在删除的文档里面     
if (deletedDocs == null || !deletedDocs.get(doc))
        break;
      skippingDoc();
    }
    return true;
  }


图1



图2



  • 大小: 41 KB
  • 大小: 39.2 KB
分享到:
评论

相关推荐

    爬取裁判文书网对docID解码用到的js

    爬取裁判文书网对docID解码用到的js function Navi(id, str_key) { var unzipid = unzip(id); // var realid = com.str.Decrypt(unzipid); var realid = com.str.Decrypt(unzipid,str_key); return realid } ...

    Python库 | os-docid-0.4.0.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:os-docid-0.4.0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    HAL库函数说明

    根据文件提供的信息,以下是对STM32 HAL库函数的详细知识点梳理: 首先,STM32的HAL库是一个标准的固件库,其目的是为了简化开发者在使用STM32微控制器时的开发流程,减少开发工作量,节约时间和成本。...

    xSeries安装Windows2000_2003后需要安装的设备驱动程序文档汇总.doc

    每个型号都有其特定的驱动程序列表,需要根据实际服务器型号和安装的操作系统来查找和安装。 安装这些驱动程序对于确保网络连接、存储控制器、显卡、声卡、网卡、RAID配置以及其他硬件设备的正常工作至关重要。此外...

    jmeter--bean shell断言所需要的包

    docId[i]=jsonObject.getString("docId"); docStatus[i]=jsonObject.getString("docStatus"); System.out.println(jsonObject.getString("docId")+":"+jsonObject.getString("docStatus")); if((docId[i]....

    远程调用用友EAI接口实例

    sb.Append("&lt;ufinterface sender=\"001\" receiver=\"u8\" roottag=\"department\" docid=\"\" proc=\"Query\" codeexchanged=\"n\"&gt;") .Append(...

    -ns-yt-el-detailpage-cpn-amzwx0ZKFGICrCQ4-docid-ek7whDs0b60-ver-:{“ ns”

    -ns-yt-el-detailpage-cpn-amzwx0ZKFGICrCQ4-docid-ek7whDs0b60-ver- {“ ns”:“ yt”,“ el”:“ detailpage”,“ cpn”:“ amzwx0ZKFGICrCQ4”,“ docid”:“ ek7whDs0b60”,“ ver”:2,“ cmt”:“ ...

    SL400装XP过程以及驱动全集

    ### 联想THINKPAD SL400笔记本XP安装及驱动详解 #### 一、安装前准备 ... - 下载地址:[http://think.lenovo.com.cn/support/driver/detail.aspx?docID=DR1216800721944&docTypeID=DOC_TYPE_DRIVER]...

    ThinkPad R400 WindowsXP驱动安装说明

    http://think.lenovo.com.cn/support/driver/detail.aspx?docID=DR1221303651950&docTypeID=DOC_TYPE_DRIVER 默认解压路径:C:\DRIVERS\WIN\INTELINF\INFINST_AUTOL.EXE 2、ATI显卡驱动程序(设备管理器中...

    javascript 的Document属性和方法集合

    - `document.getElementsByName(Name)`: 根据指定的name属性值查找并返回一组元素对象。 - `document.body.appendChild(oTag)`: 向`&lt;body&gt;`元素添加一个新的子元素。 3. **body对象** - `document.body`: 表示...

    oracle SQL优化实例

    索引唯一扫描是指Oracle使用索引查找一个或少数几个记录。这是非常高效的查询方式,尤其是当索引键具有唯一性时。 **示例代码:** ```sql SELECT empno, ename FROM emp WHERE empno = '2000'; ``` **解释:** 该...

    2011-2 第一期 System x 及相关存储产品技术支持信息周报

    进入阵列卡 Web BIOS 配置界面的方法也可在此处查找: - [《进入阵列卡 Web BIOS 配置界面》](http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=XPXP-8AF5SE) #### 知识点六:使用 SSCT 配置 x 系列服务器 ...

    云计算第三版精品课程配套PPT课件含习题(31页)第11章 中国云计算第三版技术(一).pptx

    精品云计算第三版全套课程PPT学习课件,非常适合大学生和职场人士学习,也适合老鸟复习回顾,完全可用于自学入门,很经典好用的PPT课件哦~ 第1章 大数据与云计算第三版 第2章 Google云计算第三版原理与应用(一) ...

    大话Web&Native;混合开发_58同城。pptx

    ### 大话Web&Native混合开发 #### 一、引言 随着移动互联网的迅猛发展,各类应用程序(Apps)已成为人们日常生活中不可或缺的一部分。在众多的App开发模式中,混合开发(Hybrid App Development)因其独特的优势而...

    Google搜索引擎及其实现技术.pdf

    此外,还有一个将URL转换为docID的对照文件,用于快速查找。 【总结】 Google搜索引擎的实现技术包括高效的网络爬虫策略、基于倒排文件的索引构建、以及优化的数据存储和检索结构。这些技术共同确保了Google能够在...

    thinkpad SL400改装 XP 步骤及所需驱动

    - 下载地址:[Intel 芯片组驱动](http://think.lenovo.com.cn/support/driver/detail.aspx?docID=DR1216800721944&docTypeID=DOC_TYPE_DRIVER) - 安装路径:`C:\DRIVERS\WIN\OSFIXES\INTELINF\setup.exe` - **...

    logicalDoc

    * getContent操作:用于获取文档内容,需要提供会话标识符(sid)和文档标识符(docId)。 * getFileName操作:用于获取文档名称,需要提供会话标识符(sid)和文档标识符(docId)。 * listDocuments操作:用于获取...

    爬虫代码.zip-爬虫代码.zip-爬虫代码.zip-爬虫代码.zip-爬虫代码.zip

    qsyk = WANGYI(list_url="http://c.m.163.com/nc/article/list/T1350383429665/", list_docid="T1350383429665", item_type="qingsongyike", title_key=["每日轻松一刻"]) qsyk.run() def pangbianguaitan(): ...

    爬虫代码.7z-爬虫代码.7z-爬虫代码.7z-爬虫代码.7z爬虫代码.7z-爬虫代码.7z

    qsyk = WANGYI(list_url="http://c.m.163.com/nc/article/list/T1350383429665/", list_docid="T1350383429665", item_type="qingsongyike", title_key=["每日轻松一刻"]) qsyk.run() def pangbianguaitan(): ...

Global site tag (gtag.js) - Google Analytics