lucene正向索引(续)——一个文档的所有filed+value都在fdt文件中!!!
2017-02-13 18:00
357 查看
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; |
相关文章推荐
- 复制一个文件夹下所有文件(包括子文件夹)并修改文件后缀名 java实现加密文档unlock
- 利用Lucene将被索引文件目录中的所有文件建立索引
- 利用Lucene测试索引生成的.fnm 和 .fdx 和 .fdt 和 .tii 和 .tis文件所包含的内容(详解)
- Lucene索引库查询;使用MatchAllDocsQuery查询索引目录中的所有文档;及代码示例
- sh 将mysql中所有的索引保存到一个文件中
- lucene正向索引(续)——每次commit会形成一个新的段,段"_1"的域和词向量信息可能存在"_0.fdt"和"_0.fdx”中
- Lucene索引文件结构图之一(segments&fnm&fdx&fdt)
- 归档功能:也称作索引功能,通常都是按月份进行BLOG文件的归档(也有按分类归档的),便于大家在一个页面就查找到归档日期内的所有BLOG文章
- 基于Lucene 的一个简单文件索引
- Poseidon 系统是一个日志搜索平台——认证看链接ppt,本质是索引的倒排列表和原始日志数据都存在HDFS,而文档和倒排的元数据都在NOSQL里,同时针对单个filed都使用了独立索引,使用MR来索引和搜索
- 第二周第四天(解析/过滤文件/找d盘里的所有txt文件/FileInputStream/FileOutputStream/拷贝文件/readLine读取一个文本行/在一个文档里写入内容)
- 针对这一段时间ASP.NET版中比较集中突出的问题,我写了一个完整的页面,包含显示/修改/删除/添加/排序/合并/写文件/显示图片或文档,有详细代码注释
- 一个使用多线程删除指定目录及子目录下所有指定文件的Java程序(源码)
- 一个文件搞定操作系统的所有问题
- 读取一个文件夹或子文件夹内的所有文件范例
- 如何通过ADO,获取一个数据库文件里面所有的表?
- 一个文件搞定操作系统的所有问题
- lucene建索引时的一个"Can't rename segments.new to segments"异常的原因
- 一个遍历指定目录下所有文件的例子
- 用vbs实现按创建日期的顺序列出一个文件夹中的所有文件