BinaryDocValue的读取和NumericDocValue的读取的原理是差不多的,都是在打开一个新的段时,先读取meta文件,也就是 索引文件,读取到内存,然后保存起来,再用刀某个doc的docValue的时候再去读data文件。看下读取meta文件的代码吧,是在Lucene410DocValuesProducer.readBinaryEntry(IndexInput)中:
static BinaryEntry readBinaryEntry(IndexInput meta) throws IOException { BinaryEntry entry = new BinaryEntry(); entry.format = meta.readVInt();//存储的格式 entry.missingOffset = meta.readLong();//记录那些含有值的docSet的fp entry.minLength = meta.readVInt();//byte[]长度的最小值 entry.maxLength = meta.readVInt();//byte[]长度的最大值 entry.count = meta.readVLong();//所有的doc的数量 entry.offset = meta.readLong();//真正存储docValue的部分的fp switch (entry.format) { case BINARY_FIXED_UNCOMPRESSED://没有压缩的,说明是长度一致的,直接根据id * minLength找到开始位置。 break; case BINARY_PREFIX_COMPRESSED://没有使用! entry.addressesOffset = meta.readLong(); entry.packedIntsVersion = meta.readVInt(); entry.blockSize = meta.readVInt(); entry.reverseIndexOffset = meta.readLong(); break; case BINARY_VARIABLE_UNCOMPRESSED: entry.addressesOffset = meta.readLong();//这个是记录每个doc的byte[]的长度的那一块的fp。 entry.packedIntsVersion = meta.readVInt(); entry.blockSize = meta.readVInt();//这个是读取一个块的大小,因为在存储那些数子的时候,是按照块来存储的。 break; default: throw new CorruptIndexException("Unknown format: " + entry.format + ", input=" + meta); } return entry; }
这样读取了meta文件,然后保存在内存中,我们看下具体怎么读取每个doc的docValue的吧:代码在Lucene410DocValuesProducer.getBinary(FieldInfo)中,
public BinaryDocValues getBinary(FieldInfo field) throws IOException { BinaryEntry bytes = binaries.get(field.number); switch (bytes.format) { case BINARY_FIXED_UNCOMPRESSED: return getFixedBinary(field, bytes);//所有的byte[]长度一致的格式 case BINARY_VARIABLE_UNCOMPRESSED: return getVariableBinary(field, bytes);//byte[]长度不一样的格式 case BINARY_PREFIX_COMPRESSED://没有用刀 return getCompressedBinary(field, bytes); default: throw new AssertionError(); } }
挨个看看,先看byte[]长度都一样的情况:
private BinaryDocValues getFixedBinary(FieldInfo field, final BinaryEntry bytes) throws IOException { // 因为已经知道了每个byte[]的长度,所以直接乘以数量,此时不会有missing的,即所有的doc都含有值,所以count就是值得个数 final IndexInput data = this.data.slice("fixed-binary", bytes.offset, bytes.count * bytes.maxLength);//从索引中获得指定位置的数据 final BytesRef term = new BytesRef(bytes.maxLength); final byte[] buffer = term.bytes;//读取到这个里面来 final int length = term.length = bytes.maxLength; return new LongBinaryDocValues() { @Override public BytesRef get(long id) { try { data.seek(id * length);//找到开始的位置 data.readBytes(buffer, 0, buffer.length);//读取一个byte[] return term; } catch (IOException e) { throw new RuntimeException(e); } } }; }
可以发现,如果 byte[]的长度都一样,是很容易理解的。直接用id*每个byte[]的长度即可,而且byte[]的长度是已知的,因为最大值和最小值都保存了。再看下不一样长的:
private BinaryDocValues getVariableBinary(FieldInfo field, final BinaryEntry bytes) throws IOException { //读取位置,因为当byte[]不一样的时候,会保存每个doc的byte[]的长度,这里就是将每个doc的长度读取出来(其实是按照块读取的,并不是每个doc都读取出来,不过我们不研究那个,这里假设是都读取出来了,或者是提供的功能能够得到每个doc的byte[]的开始位置) final MonotonicBlockPackedReader addresses = getAddressInstance(field, bytes); //将所有的值读取出来(也就是所有的doc的byte[]) final IndexInput data = this.data.slice("var-binary", bytes.offset, bytes.addressesOffset - bytes.offset); final BytesRef term = new BytesRef(Math.max(0, bytes.maxLength)); final byte buffer[] = term.bytes; return new LongBinaryDocValues() { @Override public BytesRef get(long id) { long startAddress = addresses.get(id);//当前doc的开始位置 long endAddress = addresses.get(id + 1);//当前doc的结束位置 int length = (int) (endAddress - startAddress);//长度,如果一个doc没有值,那么他的下一个doc的开始位置他的开始位置是一样的,则这个是0 try { data.seek(startAddress); data.readBytes(buffer, 0, length); term.length = length; return term;//返回读取到的byte[]. } catch (IOException e) { throw new RuntimeException(e); } } }; }
这样也就看完了长度不一致的读取,在读取的时候,会根据id得到开始位置, 然后再从那个大大的byte[]中根据偏移量读取。他的效率不如长度一致的byte[]的高,因为要读取两次,而长度一致的只需要读取一次。还有需要注意的就是,任何一个doc都会读取到一个BytesRef,所以要看那个记录有没有值的bitset才能决定这个doc有没有binaryDocValue。
相关推荐
lucene3源码分析
Lucene项目的文档和源码,很好的java学习资料哦
lucene索引查看工具及源码lucene索引查看工具及源码lucene索引查看工具及源码
Lucene.Net-2.9.2 c# 源码,已经用它做了查询网站
lucene全文检索案例源码 lucene全文检索案例源码
Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。该资源是Lucene的完整源码,利用源码,可以定制适合自身需要的搜索引擎。
lucene.net2.9.4.2源码版 dll版本是2.9.4.2 对2.9.4版的局部改进版
Lucene3.5全部源码,打包jar文件,可以直接打开查看源码,Lucene开发必备
Lucene源码解读、功能分析,Lucene入门
Lucene学习源码.rar
lucene.net 2.9.1 源码,lucene.net 2.9.1最新dll
这是基于lucene搜索引擎的java源码,里面数据库,包括建立索引,增量索引一应俱全,希望对大家有作用。
lucene-core-4.3.1的源码 可以用的 放心用吧 官网上很多链接都打不开
描述了Lucene中如何使用FST算法构建term的内存索引,使用了很多图,直观的展现了FST图的构建流程,能够对想了解lucene内部实现机制原理的同学有帮助。
Lucene,作为一种全文搜索的辅助工具,为我们进行条件搜索,无论是像Google,Baidu之类的搜索引 擎,还是论坛中的搜索功能,还是其它C/S架构的搜索,都带来了极大的便利和比较高的效率。本文主要是利用Lucene对MS Sql...
Lucene.net 搜索引擎 Lucene.net源码 Lucene.net中文文档; 好的东西需要分享
lucene 华电项目 源码
lucene3.0.3源码和教程
lucene5.0源码包,里面有源码、帮助文档、API、架包
Lucene 4.1 最新版本 源码 修复诸多BUG 含英文API 新增AnalyzingSuggester和FuzzySuggester等,性能优化 欢迎下载