对于SetDocValue的读取很简单,因为他的写入的格式和之前的SortedDocValue和SortedNumericDocValue有很多重复的地方,所以在读取的时候也是有很多重复的地方。
先看看最终要返回的接口吧,
public abstract class SortedSetDocValues { /** Sole constructor. (For invocation by subclass constructors, typically implicit.) */ protected SortedSetDocValues() {} /*** When returned by {@link #nextOrd()} it means there are no more ordinals for the document. */ public static final long NO_MORE_ORDS = -1; /** 读取当前的doc的下一个byte[]的排序 */ public abstract long nextOrd(); /** 设置要读取的doc的id */ public abstract void setDocument(int docID); /** 查找指定排序的byte[] */ public abstract BytesRef lookupOrd(long ord); /** 返回所有的byte[]的个数 */ public abstract long getValueCount(); /** 查询某个byte[]是否存在,如果不存在返回一个负数,这个方法被覆写了 */ public long lookupTerm(BytesRef key) { long low = 0; long high = getValueCount() - 1; while (low <= high) { long mid = (low + high) >>> 1; final BytesRef term = lookupOrd(mid); int cmp = term.compareTo(key); if (cmp < 0) { low = mid + 1; } else if (cmp > 0) { high = mid - 1; } else { return mid; // key found } } return -(low + 1); // key not found. } /** 返回迭代所有的byte[]的对象 ,这个方法也被覆写了*/ public TermsEnum termsEnum() { return new SortedSetDocValuesTermsEnum(this); } }
上面的功能很简单,基本和之前的SortedDocValue和SortedNumericDocValue一样。再看看具体的操作:
public SortedSetDocValues getSortedSet(FieldInfo field) throws IOException { SortedSetEntry ss = sortedSets.get(field.number); if (ss.format == SORTED_SINGLE_VALUED) { final SortedDocValues values = getSorted(field); return DocValues.singleton(values); } else if (ss.format != SORTED_WITH_ADDRESSES) { throw new AssertionError(); } final long valueCount = binaries.get(field.number).count;//所有的byte[]的个数 // we keep the byte[]s and list of ords on disk, these could be large final LongBinaryDocValues binary = (LongBinaryDocValues) getBinary(field);//获得所有的byte[]。 final LongValues ordinals = getNumeric(ords.get(field.number));//读取第二部分,也就是每个doc的所有的排序的地方, // but the addresses to the ord stream are in RAM, 读取第三部分,即地址部分,用于计算每个doc的排序的地址 final MonotonicBlockPackedReader ordIndex = getOrdIndexInstance(field, ordIndexes.get(field.number)); return new RandomAccessOrds() { long startOffset;//当前的doc的第一个byte[]是总的byte[]的多少个。 long offset;// long endOffset;//当前的doc的下一个doc的第一个byte[]是总的byte[]的多少个。 public long nextOrd() {//读取当前doc的下一个byte的排序 if (offset == endOffset) { return NO_MORE_ORDS; } else { long ord = ordinals.get(offset); offset++; return ord; } } public void setDocument(int docID) {//读取指定的doc, startOffset = offset = ordIndex.get(docID); endOffset = ordIndex.get(docID + 1L); } @Override public BytesRef lookupOrd(long ord) {//根据排序获得byte[] return binary.get(ord); } @Override public long getValueCount() {//所有的byte[]的个数 return valueCount; } @Override public long lookupTerm(BytesRef key) {//返回一个byte[]是否存在,如果存在返回其排序,否则返回一个负数 if (binary instanceof CompressedBinaryDocValues) {//进入 return ((CompressedBinaryDocValues) binary).lookupTerm(key); } else { return super.lookupTerm(key); } } @Override public TermsEnum termsEnum() { if (binary instanceof CompressedBinaryDocValues) {//这个是进入的,因为在存储所有的byte[]的时候,就是前缀压缩的,和之前的SortedDocValue的格式是一样的,所以返回的结果也是一样的 return ((CompressedBinaryDocValues) binary).getTermsEnum(); } else { return super.termsEnum(); } } @Override public long ordAt(int index) { return ordinals.get(startOffset + index); } @Override public int cardinality() { return (int) (endOffset - startOffset); } }; }
如果看懂了SortedDocValue其实这里也很简单。
过年夜,少写点。。