`
suichangkele
  • 浏览: 200491 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

lucene中的docValue实现源码解读(五)——BinaryDocValue的读取

阅读更多

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项目的文档和源码

    源码阅读是理解任何软件内部工作原理的最好方式,通过研究Lucene的源码,我们可以深入了解其内部的数据结构、算法实现以及优化技巧。例如,可以学习到如何实现Trie数据结构进行高效查询,或者如何使用BitSet进行布尔...

    lucene3源码分析

    ### Lucene3源码分析知识点概述 #### 一、全文检索的基本原理 ##### 1. 总论 全文检索系统是一种高效的信息检索技术,能够帮助用户在海量文档中快速找到包含特定关键词的信息。Lucene是Java领域内最受欢迎的全文...

    Lucene.Net-2.9.2 c#源码

    通过深入理解Lucene.Net 2.9.2的源码,开发者可以定制自己的分析器、优化查询性能、调整索引策略,从而在实际项目中充分发挥Lucene.Net的潜力。在构建查询网站时,结合C#的特性,可以构建出高效、灵活且用户体验良好...

    Lucene源码解读1

    【Lucene源码解读1】 Lucene是一款开源的全文搜索引擎库,由Apache软件基金会开发,广泛应用于各种信息检索系统。其强大的搜索功能和高效的性能深受开发者喜爱。在深入理解Lucene之前,我们需要先了解它的核心概念...

    lucene.net2.9.4.2源码版

    《深入剖析Lucene.NET 2.9.4.2源码》 Lucene.NET是一个开源全文搜索引擎库,它是Apache Lucene项目的.NET版本。这个源码版是2.9.4.2版本,相较于2.9.4版进行了一些局部改进,以适应.NET平台的需求和优化。在本文中...

    使用Lucene对doc、docx、pdf、txt文档进行全文检索功能的实现 - 干勾鱼的CSDN博客 - CSDN博客1

    在Java开发中,Lucene被广泛用于实现文件的全文检索功能,包括对doc、docx、pdf、txt等常见格式文档的文本内容检索。在本文中,我们将探讨如何使用Lucene对这些文件类型进行全文检索的实现。 首先,为了实现全文...

    Lucene3.5源码jar包

    总的来说,深入学习Lucene 3.5.0的源码,可以帮助开发者掌握全文检索的核心技术,了解其内部工作原理,并能灵活应用到自己的项目中。这份源码不仅适用于初学者,也是经验丰富的开发者的宝贵参考资料。通过阅读和理解...

    Lucene学习源码.rar

    本文将主要围绕Java Lucene进行深入探讨,并基于提供的“Lucene学习源码.rar”文件中的“Lucene视频教程_讲解部分源码”展开讨论。 一、Lucene核心概念 1. 文档(Document):Lucene中的基本单位,用于存储待检索...

    基于lucene搜索引擎的java源码

    学习这个源码包可以帮助你理解如何在Java环境中使用Lucene进行全文检索,以及如何实现数据库与索引之间的交互。这不仅涉及到了Lucene的核心功能,也涵盖了实际项目中常见的增量索引和数据库集成问题。通过阅读和理解...

    lucene全文检索案例源码

    通过对“lucene全文检索案例源码”的学习,我们可以理解Lucene如何在实际项目中实现全文检索。从索引构建到搜索执行,每个步骤都至关重要。通过源码的深入研究,有助于我们在实际开发中更好地运用Lucene,提升搜索...

    lucene.net 2.9.1 源码

    《深入剖析Lucene.NET 2.9.1:源码解析与应用开发》 Lucene.NET 2.9.1是开源搜索引擎库Lucene的.NET版本,它为.NET开发者提供了强大的全文检索和索引功能。这个版本的源码提供了一个宝贵的资源,帮助我们理解其内部...

    lucene 华电项目 源码

    本文将结合“lucene 华电项目 源码”,深度解析Lucene的核心原理以及在华电项目中的实际应用。 首先,我们要理解Lucene的基本架构。Lucene的核心组件包括Analyzer(分析器)、Document(文档)、IndexWriter(索引...

    lucene in action源码2

    总之,《Lucene in Action》的源码是一份宝贵的教育资源,它能帮助开发者深入理解搜索引擎的运作原理,从而在实际项目中更好地利用Lucene。通过细致研究源码,我们不仅可以解决具体的技术问题,还能培养出更强的解决...

    Lucene中的FST算法描述

    4. FSTHashMap:这是一个基于探测法实现的HashMap,其key是基于FSTNode生成的hash值,而value是FSTnode在FSTbytes数组中的位置索引。FSTHashMap可以加速判断某个节点是否已经被存储到FSTbytes中。 5. Frontier:这...

    Lucene In Action 2源码

    源码文件通常包含了书中各个章节的示例程序,这些示例涵盖了Lucene的基本用法到高级特性的实现,如文档索引、搜索查询、结果排序、过滤器、分词器、高亮显示等。通过研究这些源码,开发者可以了解如何有效地利用...

    Lucene.Net源码与说明文档

    **Lucene.Net** 是一个基于 .NET Framework 的全文搜索引擎库,它是 Apache Lucene 项目的 .NET 实现。这个开源项目提供了高效、可扩展的搜索功能,使得开发者能够在其应用程序中轻松地实现高级的文本检索功能。 **...

    运用在lucene中的中文分词算法源码

    《深入剖析Lucene中的中文分词算法源码》 在信息检索领域,Lucene作为一款强大的全文搜索引擎库,被广泛应用于各种数据检索系统。而中文分词是Lucene处理中文文本时的关键步骤,它决定了搜索的准确性和效率。本文将...

    lucene源码和程序

    在`lucene-1.4-final`这个压缩包中,包含了Lucene 1.4版本的源代码,你可以深入研究其内部实现,理解各个类和方法的工作原理。同时,这也可以帮助你定制分析器、优化搜索性能,或者扩展Lucene的功能,例如集成到你的...

    lucene源码

    深入理解 Lucene 的源码对于 Java 开发者来说,不仅可以提升对搜索引擎原理的理解,还能在实际项目中更好地利用 Lucene 的功能。 **1. Lucene 的核心组件** Lucene 的主要组成部分包括索引(Indexing)、查询解析...

    lucene索引查看工具及源码

    - **索引读取**:了解 Luke 是如何使用 Lucene 的 `IndexReader` 和 `Directory` 接口来访问和加载索引的。 - **字段和文档处理**:观察 Luke 如何获取和显示文档字段,以及如何解析和展示不同类型的字段值。 - **...

Global site tag (gtag.js) - Google Analytics