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

lucene中的docValue实现源码解读(三)——NumericDocValue的读取

阅读更多
对lucene的docValue的读取是在Lucene410DocValuesProducer中,我们看下他的构造方法,其中类的代码我也复制了一些有用的
class Lucene410DocValuesProducer extends DocValuesProducer implements Closeable {
	/** 适用于numericDocValue的docValue,key是域号,value是对应的域的meta文件的属性,在打开时候就会读取meta文件*/
	private final Map<Integer, NumericEntry> numerics;
	private final AtomicLong ramBytesUsed;
	private final IndexInput data;
	private final int maxDoc;
	private final int version;

	// memory-resident structures
	private final Map<Integer, MonotonicBlockPackedReader> addressInstances = new HashMap<>();
	private final Map<Integer, MonotonicBlockPackedReader> ordIndexInstances = new HashMap<>();

	/** expert: instantiates a new reader */
	Lucene49DocValuesProducer(SegmentReadState state, String dataCodec, String dataExtension, String metaCodec,
			String metaExtension) throws IOException {
		String metaName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, metaExtension);
		// read in the entries from the metadata file.
		ChecksumIndexInput in = state.directory.openChecksumInput(metaName, state.context);
		this.maxDoc = state.segmentInfo.getDocCount();
		boolean success = false;
		try {
			version = CodecUtil.checkHeader(in, metaCodec, Lucene49DocValuesFormat.VERSION_START,
					Lucene49DocValuesFormat.VERSION_CURRENT);
			numerics = new HashMap<>();
			。。。//省略了一些不相关的
			readFields(in, state.fieldInfos);//读取所有的docValue,包括各种类型的,这个是在meta(也就是在索引文件,dvm)中读取的

			CodecUtil.checkFooter(in);
			success = true;
		} finally {
			if (success) {
				IOUtils.close(in);
			} else {
				IOUtils.closeWhileHandlingException(in);
			}
		}

		String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
		this.data = state.directory.openInput(dataName, state.context);//打开实际的存储文件。
		success = false;
		。。。//省略

		ramBytesUsed = new AtomicLong(RamUsageEstimator.shallowSizeOfInstance(getClass()));
	}

 在构造这个读取docValue的对象的时候,就会读取索引文件,里面会读取meta文件,然后封装为XxxEntry对象,放到内存中,这个类中的private final Map<Integer, NumericEntry> numerics;属性就是根据域存放的meta文件的描述。读取meta文件在readFields方法中,里面会读取各种不同的类型的docValue,这里只看了数字类型的:

static NumericEntry readNumericEntry(IndexInput meta) throws IOException {
		
	//读取的当前的docvalue的信息,来自于meta,
	NumericEntry entry = new NumericEntry();
	entry.format = meta.readVInt();//存储的 格式,比如最大公约数差值、差值、压缩表
	entry.missingOffset = meta.readLong();//存储的missing的docs在data中的fp(偏移量)
	entry.offset = meta.readLong();//正真的存储位置的偏移量(也就是再超过上面的missingDocBitset)
	entry.count = meta.readVLong();//一共多少个doc
	switch (entry.format) {
	case GCD_COMPRESSED://基于最大公约数的
		entry.minValue = meta.readLong();//最小值
		entry.gcd = meta.readLong();//最大公约数
		entry.bitsPerValue = meta.readVInt();//每个数字占据的bit的数量,用于解码
		break;
	case TABLE_COMPRESSED://压缩表的,适用于docValue的数字比较少的时候
		final int uniqueValues = meta.readVInt();//具体的数字的个数
		if (uniqueValues > 256) {
			throw new CorruptIndexException(
					"TABLE_COMPRESSED cannot have more than 256 distinct values, input=" + meta);
		}
		entry.table = new long[uniqueValues];
		for (int i = 0; i < uniqueValues; ++i) {//读取所有的值,之前都放在meta中了。
			entry.table[i] = meta.readLong();
		}
		entry.bitsPerValue = meta.readVInt();//这个值是用于解码用的。
		break;
	case DELTA_COMPRESSED:
		entry.minValue = meta.readLong();//最小值,
		entry.bitsPerValue = meta.readVInt();//在data中用于记录某个值的位数,用于解码。
		break;
	case MONOTONIC_COMPRESSED://这个是没有的。在Lucene49DocValuesConsumer只有上面的三种格式
		entry.packedIntsVersion = meta.readVInt();
		entry.blockSize = meta.readVInt();
		break;
	default:
		throw new CorruptIndexException("Unknown format: " + entry.format + ", input=" + meta);
	}
	entry.endOffset = meta.readLong();//结束位置,
	return entry;
}

这里可以发现,是把meta文件中有用到的属性 都读取出来,然后放到内存中了,但是还没有真正的读取数字类型的docValue。真正的读取操作是在这个方法里面

@Override
public NumericDocValues getNumeric(FieldInfo field) throws IOException {
	NumericEntry entry = numerics.get(field.number);
	return getNumeric(entry);
}

 其中的numerics就是之前读取的所有的域的meta文件,里面根据域的序号进行查找的,所以更关键的方法是getNumeric方法:

//尽管我们可以使用多种类型的数字类型的,但是在存储的时候都是存储的long类型的,这里读取的也是
LongValues getNumeric(NumericEntry entry) throws IOException {
	
	RandomAccessInput slice = this.data.randomAccessSlice(entry.offset, entry.endOffset - entry.offset);//这个方法是最关键的,他会读取data文件中的指定的一块。但是是否读取到内存中,我也不知道,求帮助!
	switch (entry.format) {
	
	case DELTA_COMPRESSED://差值的
		final long delta = entry.minValue;
		final LongValues values = DirectReader.getInstance(slice, entry.bitsPerValue);
		return new LongValues() {
			@Override
			public long get(long id) {
				return delta + values.get(id);//直接读取差值+最小值即可
			}
		};
		
	case GCD_COMPRESSED://最大公约数的,和差值的差不多
		final long min = entry.minValue;
		final long mult = entry.gcd;
		final LongValues quotientReader = DirectReader.getInstance(slice, entry.bitsPerValue);
		return new LongValues() {
			@Override
			public long get(long id) {
				return min + mult * quotientReader.get(id);
			}
		};
		
	case TABLE_COMPRESSED://压缩表的,根据排序值进行读取
		final long table[] = entry.table;
		final LongValues ords = DirectReader.getInstance(slice, entry.bitsPerValue);
		return new LongValues() {
			@Override
			public long get(long id) {
				return table[(int) ords.get(id)];
			}
		};
	default:
		throw new AssertionError();
	}
}

 

在看懂了写入的前提下,读取的代码要简单的多,但是有一个重要的地方就是上面标红的randomAcessSlice方法。如果有大神看到了,希望能给我们解疑答惑一下,他到底是读取到内存中呢,还是靠操作系统加载到内存中呢还是压根就不会再内存中操作。

 还有一个需要注意的地方是,在读取的时候没有考虑了那个bitset,就是记录含有值得doc的id的bitset,所以如果读到了0,还需要判断一下是不是存在,即是不是在那个bitset中。

分享到:
评论
1 楼 粟谷_sugu 2018-06-13  
干货!!!膜拜大神,持续学习

相关推荐

    lucene3源码分析

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

    Lucene项目的文档和源码

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

    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源码版

    通过对源码的深入研究,开发者不仅可以掌握搜索引擎的底层原理,还能学习到如何在.NET环境中实现高效、稳定的搜索功能。同时,通过对2.9.4版的局部改进,该版本在性能和稳定性上都有所提升,为.NET开发者提供了更好...

    Lucene3.5源码jar包

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

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

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

    Lucene学习源码.rar

    它提供了一个简单但功能强大的API,使得开发者能够轻松地在应用中实现文本检索功能。Lucene是用Java编写的,但有多种语言的接口,包括Python、.NET等。本文将主要围绕Java Lucene进行深入探讨,并基于提供的“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是一个强大的全文检索工具,通过其API,开发者可以轻松地在Java应用中实现高效、灵活的搜索功能。无论你是希望为网站添加搜索功能,还是构建大型的企业级搜索解决方案,Lucene都是值得信赖的选择。通过...

    lucene源码

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

    lucene索引查看工具及源码

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

Global site tag (gtag.js) - Google Analytics