lucene中关于正向信息的获取——FielldCache

之前写完了docValue的内容,但是如何获取docValue呢?或者将这个问题在宽泛一些,如何获取doc的正向信息,很简单,就是FieldCache,FieldCache采取了一个单利模式,他有一个实现类叫做FieldCacheImpl。所有的获取正向信息的操作都是通过这个类的getxxx方法,在这个通用的方法里面,所有的逻辑都是一样,如果一个域有docValue,则优先会的dcoValues,如果没有则读取这个域的词典表,unInvert,即将倒排表读取到内存中,然后每个doc再进行计算,将每个doc和每个term对应起来,然后再一个大Map中存起来。从效果上来看,在第一次读取的时候,如果没有docValue则会很慢,而且即使读取到内存中也是很消耗资源的,所以在facet、sort的时候,还是建议将对应的类做docValue,这样会更快。

看一下源码吧,这里以getInts为例:

public Ints getInts(AtomicReader reader, String field, IntParser parser, boolean setDocsWithField) throws IOException {
	final NumericDocValues valuesIn = reader.getNumericDocValues(field);//优先读取docValue,
	if (valuesIn != null) {//如果没有docValue,则使用
		// Not cached here by FieldCacheImpl (cached instead
		// per-thread by SegmentReader):
		return new Ints() {
			@Override
			public int get(int docID) {
				return (int) valuesIn.get(docID);
			}
		};
	} else {//如果没有docValue,
		final FieldInfo info = reader.getFieldInfos().fieldInfo(field);
		if (info == null) {//没有这个域
			return Ints.EMPTY;
		} else if (info.hasDocValues()) {//有docValue,报错
			throw new IllegalStateException("Type mismatch: " + field + " was indexed as " + info.getDocValuesType());
		} else if (!info.isIndexed()) {//没有建立索引,则无法读取词典表,返回empty
			return Ints.EMPTY;
		}
		return (Ints) caches.get(Integer.TYPE).get(reader, new CacheKey(field, parser), setDocsWithField);//这个就是读取词典表。
	}
}

 最关键的就是最后一行,从cache中获得int类型的对象,在FiledCacheImpl初始化的时候,就会向一个很大的map中写入很多对象,作为代理类,然后再读取的时候再从词典表中读取具体的term,然后再放入到原来的map中缓存起来,这样就完成了再没有docValue的情况下正向信息的获取。

猜你喜欢

转载自suichangkele.iteye.com/blog/2411060