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) { // Can only reuse if incoming enum is also a MultiDocsEnum // ... and was previously created w/ this MultiTermsEnum: if (reuse is null || !(reuse is MultiDocsEnum docsEnum) || !docsEnum.CanReuse(this)) { docsEnum = new MultiDocsEnum(this, subs.Length); } int upto = 0; for (int i = 0; i < numTop; i++) { TermsEnumWithSlice entry = top[i]; IBits b; if (liveDocs is MultiBits multiLiveDocs) { // 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; } if (Debugging.AssertsEnabled) { Debugging.Assert(entry.Index < docsEnum.subDocsEnum.Length, "{0} vs {1}; {2}", entry.Index, 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? if (Debugging.AssertsEnabled) { Debugging.Assert(false, "One of our subs cannot provide a docsenum"); } } } if (upto == 0) { return(null); } else { return(docsEnum.Reset(subDocs, upto)); } }