/// <summary> /// The terms array must be newly created <see cref="TermsEnum"/>, ie /// <see cref="TermsEnum.Next()"/> has not yet been called. /// </summary> public TermsEnum Reset(TermsEnumIndex[] termsEnumsIndex) { if (Debugging.AssertsEnabled) { Debugging.Assert(termsEnumsIndex.Length <= top.Length); } numSubs = 0; numTop = 0; termComp = null; queue.Clear(); for (int i = 0; i < termsEnumsIndex.Length; i++) { TermsEnumIndex termsEnumIndex = termsEnumsIndex[i]; if (Debugging.AssertsEnabled) { Debugging.Assert(termsEnumIndex != null); } // init our term comp if (termComp == null) { queue.termComp = termComp = termsEnumIndex.TermsEnum.Comparer; } else { // We cannot merge sub-readers that have // different TermComps IComparer <BytesRef> subTermComp = termsEnumIndex.TermsEnum.Comparer; if (subTermComp != null && !subTermComp.Equals(termComp)) { throw new InvalidOperationException("sub-readers have different BytesRef.Comparers: " + subTermComp + " vs " + termComp + "; cannot merge"); } } BytesRef term = termsEnumIndex.TermsEnum.Next(); if (term != null) { TermsEnumWithSlice entry = subs[termsEnumIndex.SubIndex]; entry.Reset(termsEnumIndex.TermsEnum, term); queue.Add(entry); currentSubs[numSubs++] = entry; } else { // field has no terms } } if (queue.Count == 0) { return(TermsEnum.EMPTY); } else { return(this); } }
/// <summary> /// Sole constructor. </summary> /// <param name="slices"> Which sub-reader slices we should /// merge.</param> public MultiTermsEnum(ReaderSlice[] slices) { queue = new TermMergeQueue(slices.Length); top = new TermsEnumWithSlice[slices.Length]; subs = new TermsEnumWithSlice[slices.Length]; subDocs = new MultiDocsEnum.EnumWithSlice[slices.Length]; subDocsAndPositions = new MultiDocsAndPositionsEnum.EnumWithSlice[slices.Length]; for (int i = 0; i < slices.Length; i++) { subs[i] = new TermsEnumWithSlice(i, slices[i]); subDocs[i] = new MultiDocsEnum.EnumWithSlice(); subDocs[i].Slice = slices[i]; subDocsAndPositions[i] = new MultiDocsAndPositionsEnum.EnumWithSlice(); subDocsAndPositions[i].Slice = slices[i]; } currentSubs = new TermsEnumWithSlice[slices.Length]; }
public override DocsAndPositionsEnum DocsAndPositions(IBits liveDocs, DocsAndPositionsEnum reuse, DocsAndPositionsFlags flags) { MultiDocsAndPositionsEnum docsAndPositionsEnum; // Can only reuse if incoming enum is also a MultiDocsAndPositionsEnum if (reuse != null && reuse is MultiDocsAndPositionsEnum) { docsAndPositionsEnum = (MultiDocsAndPositionsEnum)reuse; // ... and was previously created w/ this MultiTermsEnum: if (!docsAndPositionsEnum.CanReuse(this)) { docsAndPositionsEnum = new MultiDocsAndPositionsEnum(this, subs.Length); } } else { docsAndPositionsEnum = new MultiDocsAndPositionsEnum(this, subs.Length); } MultiBits multiLiveDocs; if (liveDocs is MultiBits) { multiLiveDocs = (MultiBits)liveDocs; } else { multiLiveDocs = null; } int upto = 0; for (int i = 0; i < numTop; i++) { TermsEnumWithSlice entry = top[i]; IBits b; if (multiLiveDocs != null) { // Optimize for common case: requested skip docs is a // congruent sub-slice of MultiBits: in this case, we // just pull the liveDocs from the sub reader, rather // than making the inefficient // Slice(Multi(sub-readers)): MultiBits.SubResult sub = multiLiveDocs.GetMatchingSub(top[i].SubSlice); if (sub.Matches) { b = sub.Result; } else { // custom case: requested skip docs is foreign: // must slice it on every access (very // inefficient) b = new BitsSlice(liveDocs, top[i].SubSlice); } } else if (liveDocs != null) { b = new BitsSlice(liveDocs, top[i].SubSlice); } else { // no deletions b = null; } if (Debugging.AssertsEnabled) { Debugging.Assert(entry.Index < docsAndPositionsEnum.subDocsAndPositionsEnum.Length, () => entry.Index + " vs " + docsAndPositionsEnum.subDocsAndPositionsEnum.Length + "; " + subs.Length); } DocsAndPositionsEnum subPostings = entry.Terms.DocsAndPositions(b, docsAndPositionsEnum.subDocsAndPositionsEnum[entry.Index], flags); if (subPostings != null) { docsAndPositionsEnum.subDocsAndPositionsEnum[entry.Index] = subPostings; subDocsAndPositions[upto].DocsAndPositionsEnum = subPostings; subDocsAndPositions[upto].Slice = entry.SubSlice; upto++; } else { if (entry.Terms.Docs(b, null, DocsFlags.NONE) != null) { // At least one of our subs does not store // offsets or positions -- we can't correctly // produce a MultiDocsAndPositions enum return(null); } } } if (upto == 0) { return(null); } else { return(docsAndPositionsEnum.Reset(subDocsAndPositions, upto)); } }
public override DocsEnum Docs(IBits liveDocs, DocsEnum reuse, DocsFlags flags) { MultiDocsEnum docsEnum; // Can only reuse if incoming enum is also a MultiDocsEnum if (reuse != null && reuse is MultiDocsEnum) { docsEnum = (MultiDocsEnum)reuse; // ... and was previously created w/ this MultiTermsEnum: if (!docsEnum.CanReuse(this)) { docsEnum = new MultiDocsEnum(this, subs.Length); } } else { docsEnum = new MultiDocsEnum(this, subs.Length); } MultiBits multiLiveDocs; if (liveDocs is MultiBits) { multiLiveDocs = (MultiBits)liveDocs; } else { multiLiveDocs = null; } int upto = 0; for (int i = 0; i < numTop; i++) { TermsEnumWithSlice entry = top[i]; IBits b; if (multiLiveDocs != null) { // optimize for common case: requested skip docs is a // congruent sub-slice of MultiBits: in this case, we // just pull the liveDocs from the sub reader, rather // than making the inefficient // Slice(Multi(sub-readers)): MultiBits.SubResult sub = multiLiveDocs.GetMatchingSub(entry.SubSlice); if (sub.Matches) { b = sub.Result; } else { // custom case: requested skip docs is foreign: // must slice it on every access b = new BitsSlice(liveDocs, entry.SubSlice); } } else if (liveDocs != null) { b = new BitsSlice(liveDocs, entry.SubSlice); } else { // no deletions b = null; } Debug.Assert(entry.Index < docsEnum.subDocsEnum.Length, entry.Index + " vs " + docsEnum.subDocsEnum.Length + "; " + subs.Length); DocsEnum subDocsEnum = entry.Terms.Docs(b, docsEnum.subDocsEnum[entry.Index], flags); if (subDocsEnum != null) { docsEnum.subDocsEnum[entry.Index] = subDocsEnum; subDocs[upto].DocsEnum = subDocsEnum; subDocs[upto].Slice = entry.SubSlice; upto++; } else { // should this be an error? Debug.Assert(false, "One of our subs cannot provide a docsenum"); } } if (upto == 0) { return(null); } else { return(docsEnum.Reset(subDocs, upto)); } }