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。
相关推荐
源码阅读是理解任何软件内部工作原理的最好方式,通过研究Lucene的源码,我们可以深入了解其内部的数据结构、算法实现以及优化技巧。例如,可以学习到如何实现Trie数据结构进行高效查询,或者如何使用BitSet进行布尔...
### Lucene3源码分析知识点概述 #### 一、全文检索的基本原理 ##### 1. 总论 全文检索系统是一种高效的信息检索技术,能够帮助用户在海量文档中快速找到包含特定关键词的信息。Lucene是Java领域内最受欢迎的全文...
通过深入理解Lucene.Net 2.9.2的源码,开发者可以定制自己的分析器、优化查询性能、调整索引策略,从而在实际项目中充分发挥Lucene.Net的潜力。在构建查询网站时,结合C#的特性,可以构建出高效、灵活且用户体验良好...
【Lucene源码解读1】 Lucene是一款开源的全文搜索引擎库,由Apache软件基金会开发,广泛应用于各种信息检索系统。其强大的搜索功能和高效的性能深受开发者喜爱。在深入理解Lucene之前,我们需要先了解它的核心概念...
《深入剖析Lucene.NET 2.9.4.2源码》 Lucene.NET是一个开源全文搜索引擎库,它是Apache Lucene项目的.NET版本。这个源码版是2.9.4.2版本,相较于2.9.4版进行了一些局部改进,以适应.NET平台的需求和优化。在本文中...
在Java开发中,Lucene被广泛用于实现文件的全文检索功能,包括对doc、docx、pdf、txt等常见格式文档的文本内容检索。在本文中,我们将探讨如何使用Lucene对这些文件类型进行全文检索的实现。 首先,为了实现全文...
总的来说,深入学习Lucene 3.5.0的源码,可以帮助开发者掌握全文检索的核心技术,了解其内部工作原理,并能灵活应用到自己的项目中。这份源码不仅适用于初学者,也是经验丰富的开发者的宝贵参考资料。通过阅读和理解...
本文将主要围绕Java Lucene进行深入探讨,并基于提供的“Lucene学习源码.rar”文件中的“Lucene视频教程_讲解部分源码”展开讨论。 一、Lucene核心概念 1. 文档(Document):Lucene中的基本单位,用于存储待检索...
学习这个源码包可以帮助你理解如何在Java环境中使用Lucene进行全文检索,以及如何实现数据库与索引之间的交互。这不仅涉及到了Lucene的核心功能,也涵盖了实际项目中常见的增量索引和数据库集成问题。通过阅读和理解...
通过对“lucene全文检索案例源码”的学习,我们可以理解Lucene如何在实际项目中实现全文检索。从索引构建到搜索执行,每个步骤都至关重要。通过源码的深入研究,有助于我们在实际开发中更好地运用Lucene,提升搜索...
《深入剖析Lucene.NET 2.9.1:源码解析与应用开发》 Lucene.NET 2.9.1是开源搜索引擎库Lucene的.NET版本,它为.NET开发者提供了强大的全文检索和索引功能。这个版本的源码提供了一个宝贵的资源,帮助我们理解其内部...
本文将结合“lucene 华电项目 源码”,深度解析Lucene的核心原理以及在华电项目中的实际应用。 首先,我们要理解Lucene的基本架构。Lucene的核心组件包括Analyzer(分析器)、Document(文档)、IndexWriter(索引...
总之,《Lucene in Action》的源码是一份宝贵的教育资源,它能帮助开发者深入理解搜索引擎的运作原理,从而在实际项目中更好地利用Lucene。通过细致研究源码,我们不仅可以解决具体的技术问题,还能培养出更强的解决...
4. FSTHashMap:这是一个基于探测法实现的HashMap,其key是基于FSTNode生成的hash值,而value是FSTnode在FSTbytes数组中的位置索引。FSTHashMap可以加速判断某个节点是否已经被存储到FSTbytes中。 5. Frontier:这...
源码文件通常包含了书中各个章节的示例程序,这些示例涵盖了Lucene的基本用法到高级特性的实现,如文档索引、搜索查询、结果排序、过滤器、分词器、高亮显示等。通过研究这些源码,开发者可以了解如何有效地利用...
**Lucene.Net** 是一个基于 .NET Framework 的全文搜索引擎库,它是 Apache Lucene 项目的 .NET 实现。这个开源项目提供了高效、可扩展的搜索功能,使得开发者能够在其应用程序中轻松地实现高级的文本检索功能。 **...
《深入剖析Lucene中的中文分词算法源码》 在信息检索领域,Lucene作为一款强大的全文搜索引擎库,被广泛应用于各种数据检索系统。而中文分词是Lucene处理中文文本时的关键步骤,它决定了搜索的准确性和效率。本文将...
在`lucene-1.4-final`这个压缩包中,包含了Lucene 1.4版本的源代码,你可以深入研究其内部实现,理解各个类和方法的工作原理。同时,这也可以帮助你定制分析器、优化搜索性能,或者扩展Lucene的功能,例如集成到你的...
深入理解 Lucene 的源码对于 Java 开发者来说,不仅可以提升对搜索引擎原理的理解,还能在实际项目中更好地利用 Lucene 的功能。 **1. Lucene 的核心组件** Lucene 的主要组成部分包括索引(Indexing)、查询解析...
- **索引读取**:了解 Luke 是如何使用 Lucene 的 `IndexReader` 和 `Directory` 接口来访问和加载索引的。 - **字段和文档处理**:观察 Luke 如何获取和显示文档字段,以及如何解析和展示不同类型的字段值。 - **...