4.1.3. 域(Field)的数据信息(.fdt,.fdx)

  • 域数据文件(fdt):

    • 真正保存存储域(stored field)信息的是fdt文件
    • 在一个段(segment)中总共有segment size篇文档,所以fdt文件中共有segment size个项,每一项保存一篇文档的域的信息
    • 对于每一篇文档,一开始是一个fieldcount,也即此文档包含的域的数目,接下来是fieldcount个项,每一项保存一个域的信息。
    • 对于每一个域,fieldnum是域号,接着是一个8位的byte,最低一位表示此域是否分词(tokenized),倒数第二位表示此域是保存字符串数据还是二进制数据,倒数第三位表示此域是否被压缩,再接下来就是存储域的值,比如new Field("title", "lucene in action", Field.Store.Yes, …),则此处存放的就是"lucene in action"这个字符串。
  • 域索引文件(fdx)
    • 由域数据文件格式我们知道,每篇文档包含的域的个数,每个存储域的值都是不一样的,因而域数据文件中segment size篇文档,每篇文档占用的大小也是不一样的,那么如何在fdt中辨别每一篇文档的起始地址和终止地址呢,如何能够更快的找到第n篇文档的存储域的信息呢?就是要借助域索引文件。
    • 域索引文件也总共有segment size个项,每篇文档都有一个项,每一项都是一个long,大小固定,每一项都是对应的文档在fdt文件中的起始地址的偏移量,这样如果我们想找到第n篇文档的存储域的信息,只要在fdx中找到第n项,然后按照取出的long作为偏移量,就可以在fdt文件中找到对应的存储域的信息。
  • 读取域数据信息的代码如下:

Document FieldsReader.doc(int n, FieldSelector fieldSelector)

  • long position = indexStream.readLong();//indexStream points to ".fdx"
  • fieldsStream.seek(position);//fieldsStream points to "fdt"
  • int numFields = fieldsStream.readVInt();
  • for (int i = 0; i < numFields; i++)
    • int fieldNumber = fieldsStream.readVInt();
    • byte bits = fieldsStream.readByte();
    • boolean compressed = (bits & FieldsWriter.FIELD_IS_COMPRESSED) != 0;
    • boolean tokenize = (bits & FieldsWriter.FIELD_IS_TOKENIZED) != 0;
    • boolean binary = (bits & FieldsWriter.FIELD_IS_BINARY) != 0;
    • if (binary)
      • int toRead = fieldsStream.readVInt();
      • final byte[] b = new byte[toRead];
      • fieldsStream.readBytes(b, 0, b.length);
      • if (compressed)
        • int toRead = fieldsStream.readVInt();
        • final byte[] b = new byte[toRead];
        • fieldsStream.readBytes(b, 0, b.length);
        • uncompress(b),
    • else
      • fieldsStream.readString()

4.1.3. 词向量(Term Vector)的数据信息(.tvx,.tvd,.tvf)——term vector用于打分,存储StoreTermVectors的field 

词向量信息是从索引(index)到文档(document)到域(field)到词(term)的正向信息,有了词向量信息,我们就可以得到一篇文档包含那些词的信息。

  • 词向量索引文件(tvx)

    • 一个段(segment)包含N篇文档,此文件就有N项,每一项代表一篇文档。
    • 每一项包含两部分信息:第一部分是词向量文档文件(tvd)中此文档的偏移量,第二部分是词向量域文件(tvf)中此文档的第一个域的偏移量。
  • 词向量文档文件(tvd)
    • 一个段(segment)包含N篇文档,此文件就有N项,每一项包含了此文档的所有的域的信息。
    • 每一项首先是此文档包含的域的个数NumFields,然后是一个NumFields大小的数组,数组的每一项是域号。然后是一个(NumFields - 1)大小的数组,由前面我们知道,每篇文档的第一个域在tvf中的偏移量在tvx文件中保存,而其他(NumFields - 1)个域在tvf中的偏移量就是第一个域的偏移量加上这(NumFields - 1)个数组的每一项的值。
  • 词向量域文件(tvf)
    • 此文件包含了此段中的所有的域,并不对文档做区分,到底第几个域到第几个域是属于那篇文档,是由tvx中的第一个域的偏移量以及tvd中的(NumFields - 1)个域的偏移量来决定的。
    • 对于每一个域,首先是此域包含的词的个数NumTerms,然后是一个8位的byte,最后一位是指定是否保存位置信息,倒数第二位是指定是否保存偏移量信息。然后是NumTerms个项的数组,每一项代表一个词(Term),对于每一个词,由词的文本TermText,词频TermFreq(也即此词在此文档中出现的次数),词的位置信息,词的偏移量信息。
  • 读取词向量数据信息的代码如下:

TermVectorsReader.get(int docNum, String field, TermVectorMapper)

  • int fieldNumber = fieldInfos.fieldNumber(field);//通过field名字得到field号
  • seekTvx(docNum);//在tvx文件中按docNum文档号找到相应文档的项
  • long tvdPosition = tvx.readLong();//找到tvd文件中相应文档的偏移量
  • tvd.seek(tvdPosition);//在tvd文件中按偏移量找到相应文档的项
  • int fieldCount = tvd.readVInt();//此文档包含的域的个数。
  • for (int i = 0; i < fieldCount; i++) //按域号查找域
    • number = tvd.readVInt();
    • if (number == fieldNumber)
      • found = i;
  • position = tvx.readLong();//在tvx中读出此文档的第一个域在tvf中的偏移量
  • for (int i = 1; i <= found; i++)
    • position += tvd.readVLong();//加上所要找的域在tvf中的偏移量
  • tvf.seek(position);
  • int numTerms = tvf.readVInt();
  • byte bits = tvf.readByte();
  • storePositions = (bits & STORE_POSITIONS_WITH_TERMVECTOR) != 0;
  • storeOffsets = (bits & STORE_OFFSET_WITH_TERMVECTOR) != 0;
  • for (int i = 0; i < numTerms; i++)
    • start = tvf.readVInt();
    • deltaLength = tvf.readVInt();
    • totalLength = start + deltaLength;
    • tvf.readBytes(byteBuffer, start, deltaLength);
    • term = new String(byteBuffer, 0, totalLength, "UTF-8");
    • if (storePositions)
      • positions = new int[freq];
      • int prevPosition = 0;
      • for (int j = 0; j < freq; j++)
        • positions[j] = prevPosition + tvf.readVInt();
        • prevPosition = positions[j];
    • if (storeOffsets)
      • offsets = new TermVectorOffsetInfo[freq];
      • int prevOffset = 0;
      • for (int j = 0; j < freq; j++)
      • int startOffset = prevOffset + tvf.readVInt();
      • int endOffset = startOffset + tvf.readVInt();
      • offsets[j] = new TermVectorOffsetInfo(startOffset, endOffset);
      • prevOffset = endOffset;
 

lucene正向索引(续)——一个文档的所有filed+value都在fdt文件中!!!的更多相关文章

  1. Lucene 写入一个文档到该文档可搜索延迟是多少?

    我看的是最初版的lucene,1.4.3 结论是新写入的文档会先写入内存中,只有当到达一定阈值后才会刷新进磁盘,而搜索可以搜索到的数据由最初定义IndexSearcher时磁盘里的段数据决定,如果想要 ...

  2. lucene正向索引——正向信息,Index –> Segments (segments.gen, segments_N) –> Field(fnm, fdx, fdt) –> Term (tvx, tvd, tvf)

    转自:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623599.html 上面曾经交代过,Lucene保存了从Index到Segm ...

  3. 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词

    package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import org.apache.solr. ...

  4. elasticsearch 基础 —— 索引、更新文档

    索引文档 通过使用 index API ,文档可以被 索引 -- 存储和使文档可被搜索 . 但是首先,我们要确定文档的位置.正如我们刚刚讨论的,一个文档的 _index . _type 和 _id 唯 ...

  5. ElasticSearch 基本概念 and 索引操作 and 文档操作 and 批量操作 and 结构化查询 and 过滤查询

    基本概念 索引: 类似于MySQL的表.索引的结构为全文搜索作准备,不存储原始的数据. 索引可以做分布式.每一个索引有一个或者多个分片 shard.每一个分片可以有多个副本 replica. 文档: ...

  6. Java:多个文档合并输出到一个文档

    多个文档合并输出到一个文档 方法:Java NIO package First; import java.io.File; import java.io.FileInputStream; import ...

  7. iframe 元素会创建包含另外一个文档的内联框架(即行内框架)

    HTML 与 XHTML 之间的差异 在 HTML 4.1 Strict DTD 和 XHTML 1.0 Strict DTD 中,不支持 iframe 元素. 提示和注释: 提示:您可以把需要的文本 ...

  8. java 写一个"HelloJavaWorld你好世界"输出到操作系统文件Hello.txt文件中

    package com.beiwo.homework; import java.io.File; import java.io.FileOutputStream; import java.io.IOE ...

  9. lucene正向索引(续)——每次commit会形成一个新的段,段"_1"的域和词向量信息可能存在"_0.fdt"和"_0.fdx”中

    DocStoreOffset DocStoreSegment DocStoreIsCompoundFile 对于域(Stored Field)和词向量(Term Vector)的存储可以有不同的方式, ...

随机推荐

  1. JS 客户端(浏览器)存储数据之 localStorage、sessionStorage和indexDB

    基本概念 1.localStorage和sessionStorage是HTML5 Web存储的提供的两种存储方式,在IE7以上以及大多数浏览器都是支持的 2.localStorage和sessionS ...

  2. javscript函数的运用

    函数,一段能够自动完成某些功能的代码块,函数的出现,既解决了重复使用重一功能的需求,又可以避免代码的臃肿性. 使用函数有两个要求:必须调用后才可以执行;函数名不要和关键字以及系统函数相同; 函数主要有 ...

  3. 【小知识点】js无需刷新在url地址添加参数

    今天后端同事找我,问我一个关于js无需刷新在url地址添加参数的方法. 然后我百度啊,终于在一篇文章找到了办法,非常简单的一句代码. window.history.pushState({}, 0, w ...

  4. csv注入复现代码

    以下代码生成的csv文件,使用Microsoft Execl能成功弹出计算器,虽然打开时有安全提示,但是大多数src还是会接收该类漏洞 -------------------------------- ...

  5. WebApi 接口恶意请求限制

    为了防止爬虫以及恶意请求,我们适当的为API增加一个请求限制   WebApiThrottle限流框架    WebApiThrottle支持自定义配置各种限流策略.可以根据不同场景配置多个不同的限制 ...

  6. JS知识体系【JQ】附加理论+视频地址铺助学习

    理论部分:https://www.jianshu.com/p/e10792076c6e  //不吃鱼的猫_8e95---简书平台 https://www.cnblogs.com/hongqin/p/5 ...

  7. 创建虚拟目录 http://localhost:1001/ 失败,错误: 无法创建网站

    使用vs2015打开一个vs2008项目报错了. 最后网上找到的解决方案, 1,打开编辑xxx.csproj文件: 2,找到节点ProjectExtensions注释掉: 3,重新加载就好了.

  8. 多个ip地址匹配正则表达式

    匹配规则:多个ip地址使用,号进行分割 例如:1.1.1.1,2.2.2.2var iplist =/^((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}( ...

  9. 运输层3——传输控制协议TCP概述

    目录 1. TCP最主要的特点 2. TCP的连接 3. socket在不同场景中的含义 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户 ...

  10. 关于zsh-autosuggestions插件导致粘贴内容很慢的问题

    zsh开启autosuggestions 插件的时候,在终端中粘贴大量的内容的时候,会粘贴的很慢,基本上是一个字符一个字符的粘贴的. 解决方案 在.zshrc文件中配置以下内容: # This spe ...