diff --git a/server/src/main/java/org/opensearch/index/mapper/DocumentMapper.java b/server/src/main/java/org/opensearch/index/mapper/DocumentMapper.java index 3ada04b41abd2..f3ae8e39b78dc 100644 --- a/server/src/main/java/org/opensearch/index/mapper/DocumentMapper.java +++ b/server/src/main/java/org/opensearch/index/mapper/DocumentMapper.java @@ -38,6 +38,7 @@ import org.apache.lucene.search.ScoreMode; import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Weight; +import org.apache.lucene.util.BitSet; import org.apache.lucene.util.BytesRef; import org.opensearch.OpenSearchGenerationException; import org.opensearch.common.annotation.PublicApi; @@ -53,6 +54,7 @@ import org.opensearch.index.analysis.IndexAnalyzers; import org.opensearch.index.mapper.MapperService.MergeReason; import org.opensearch.index.mapper.MetadataFieldMapper.TypeParser; +import org.opensearch.search.fetch.subphase.InnerHitsContext; import org.opensearch.search.internal.SearchContext; import java.io.IOException; @@ -270,25 +272,14 @@ public ParsedDocument createNoopTombstoneDoc(String index, String reason) throws * Returns the best nested {@link ObjectMapper} instances that is in the scope of the specified nested docId. */ public ObjectMapper findNestedObjectMapper(int nestedDocId, SearchContext sc, LeafReaderContext context) throws IOException { + if (sc instanceof InnerHitsContext.InnerHitSubContext) { + ObjectMapper objectMapper = objectMappers().get(((InnerHitsContext.InnerHitSubContext) sc).getName()); + assert containSubDocIdWithObjectMapper(nestedDocId, objectMapper, sc, context); + return objectMapper; + } ObjectMapper nestedObjectMapper = null; for (ObjectMapper objectMapper : objectMappers().values()) { - if (!objectMapper.nested().isNested()) { - continue; - } - - Query filter = objectMapper.nestedTypeFilter(); - if (filter == null) { - continue; - } - // We can pass down 'null' as acceptedDocs, because nestedDocId is a doc to be fetched and - // therefore is guaranteed to be a live doc. - final Weight nestedWeight = filter.createWeight(sc.searcher(), ScoreMode.COMPLETE_NO_SCORES, 1f); - Scorer scorer = nestedWeight.scorer(context); - if (scorer == null) { - continue; - } - - if (scorer.iterator().advance(nestedDocId) == nestedDocId) { + if(containSubDocIdWithObjectMapper(nestedDocId, objectMapper, sc, context)) { if (nestedObjectMapper == null) { nestedObjectMapper = objectMapper; } else { @@ -301,6 +292,26 @@ public ObjectMapper findNestedObjectMapper(int nestedDocId, SearchContext sc, Le return nestedObjectMapper; } + private boolean containSubDocIdWithObjectMapper(int nestedDocId, ObjectMapper objectMapper, + SearchContext sc, LeafReaderContext context) throws IOException { + if (!objectMapper.nested().isNested()) { + return false; + } + Query filter = objectMapper.nestedTypeFilter(); + if (filter == null) { + return false; + } + // We can pass down 'null' as acceptedDocs, because nestedDocId is a doc to be fetched and + // therefore is guaranteed to be a live doc. + BitSet nesteDocIds = sc.bitsetFilterCache().getBitSetProducer(filter).getBitSet(context); + boolean result; + if (nesteDocIds != null && nesteDocIds.get(nestedDocId)) { + return true; + } else { + return false; + } + } + public DocumentMapper merge(Mapping mapping, MergeReason reason) { Mapping merged = this.mapping.merge(mapping, reason); return new DocumentMapper(mapperService, merged); diff --git a/server/src/main/java/org/opensearch/search/fetch/FetchPhase.java b/server/src/main/java/org/opensearch/search/fetch/FetchPhase.java index 1698f41caaf2b..e52aa3443fecd 100644 --- a/server/src/main/java/org/opensearch/search/fetch/FetchPhase.java +++ b/server/src/main/java/org/opensearch/search/fetch/FetchPhase.java @@ -501,7 +501,6 @@ private SearchHit.NestedIdentity getInternalNestedIdentity( ObjectMapper current = nestedObjectMapper; String originalName = nestedObjectMapper.name(); SearchHit.NestedIdentity nestedIdentity = null; - final IndexSettings indexSettings = context.getQueryShardContext().getIndexSettings(); do { Query parentFilter; nestedParentObjectMapper = current.getParentObjectMapper(mapperService); @@ -520,14 +519,11 @@ private SearchHit.NestedIdentity getInternalNestedIdentity( current = nestedParentObjectMapper; continue; } - final Weight childWeight = context.searcher() - .createWeight(context.searcher().rewrite(childFilter), ScoreMode.COMPLETE_NO_SCORES, 1f); - Scorer childScorer = childWeight.scorer(subReaderContext); - if (childScorer == null) { + BitSet childIter = context.bitsetFilterCache().getBitSetProducer(context.searcher().rewrite(childFilter)).getBitSet(subReaderContext); + if (childIter == null) { current = nestedParentObjectMapper; continue; } - DocIdSetIterator childIter = childScorer.iterator(); BitSet parentBits = context.bitsetFilterCache().getBitSetProducer(parentFilter).getBitSet(subReaderContext); @@ -541,8 +537,8 @@ private SearchHit.NestedIdentity getInternalNestedIdentity( * that appear before him. */ int previousParent = parentBits.prevSetBit(currentParent); - for (int docId = childIter.advance(previousParent + 1); docId < nestedSubDocId - && docId != DocIdSetIterator.NO_MORE_DOCS; docId = childIter.nextDoc()) { + for (int docId = childIter.nextSetBit(previousParent + 1); docId < nestedSubDocId + && docId != DocIdSetIterator.NO_MORE_DOCS; docId = childIter.nextSetBit(docId + 1)) { offset++; } currentParent = nestedSubDocId;