35
35
import org .apache .lucene .document .StoredField ;
36
36
import org .apache .lucene .index .LeafReaderContext ;
37
37
import org .apache .lucene .search .Query ;
38
- import org .apache .lucene .search .ScoreMode ;
39
- import org .apache .lucene .search .Scorer ;
40
- import org .apache .lucene .search .Weight ;
38
+ import org .apache .lucene .util .BitSet ;
41
39
import org .apache .lucene .util .BytesRef ;
42
40
import org .opensearch .OpenSearchGenerationException ;
43
41
import org .opensearch .common .annotation .PublicApi ;
53
51
import org .opensearch .index .analysis .IndexAnalyzers ;
54
52
import org .opensearch .index .mapper .MapperService .MergeReason ;
55
53
import org .opensearch .index .mapper .MetadataFieldMapper .TypeParser ;
54
+ import org .opensearch .index .query .NestedQueryBuilder ;
56
55
import org .opensearch .search .internal .SearchContext ;
57
56
58
57
import java .io .IOException ;
@@ -270,25 +269,15 @@ public ParsedDocument createNoopTombstoneDoc(String index, String reason) throws
270
269
* Returns the best nested {@link ObjectMapper} instances that is in the scope of the specified nested docId.
271
270
*/
272
271
public ObjectMapper findNestedObjectMapper (int nestedDocId , SearchContext sc , LeafReaderContext context ) throws IOException {
272
+ if (sc instanceof NestedQueryBuilder .NestedInnerHitSubContext ) {
273
+ ObjectMapper objectMapper = ((NestedQueryBuilder .NestedInnerHitSubContext ) sc ).getChildObjectMapper ();
274
+ assert objectMappers ().containsKey (objectMapper .fullPath ());
275
+ assert containSubDocIdWithObjectMapper (nestedDocId , objectMapper , sc , context );
276
+ return objectMapper ;
277
+ }
273
278
ObjectMapper nestedObjectMapper = null ;
274
279
for (ObjectMapper objectMapper : objectMappers ().values ()) {
275
- if (!objectMapper .nested ().isNested ()) {
276
- continue ;
277
- }
278
-
279
- Query filter = objectMapper .nestedTypeFilter ();
280
- if (filter == null ) {
281
- continue ;
282
- }
283
- // We can pass down 'null' as acceptedDocs, because nestedDocId is a doc to be fetched and
284
- // therefore is guaranteed to be a live doc.
285
- final Weight nestedWeight = filter .createWeight (sc .searcher (), ScoreMode .COMPLETE_NO_SCORES , 1f );
286
- Scorer scorer = nestedWeight .scorer (context );
287
- if (scorer == null ) {
288
- continue ;
289
- }
290
-
291
- if (scorer .iterator ().advance (nestedDocId ) == nestedDocId ) {
280
+ if (containSubDocIdWithObjectMapper (nestedDocId , objectMapper , sc , context )) {
292
281
if (nestedObjectMapper == null ) {
293
282
nestedObjectMapper = objectMapper ;
294
283
} else {
@@ -301,6 +290,25 @@ public ObjectMapper findNestedObjectMapper(int nestedDocId, SearchContext sc, Le
301
290
return nestedObjectMapper ;
302
291
}
303
292
293
+ private boolean containSubDocIdWithObjectMapper (int nestedDocId , ObjectMapper objectMapper , SearchContext sc , LeafReaderContext context )
294
+ throws IOException {
295
+ if (!objectMapper .nested ().isNested ()) {
296
+ return false ;
297
+ }
298
+ Query filter = objectMapper .nestedTypeFilter ();
299
+ if (filter == null ) {
300
+ return false ;
301
+ }
302
+ // We can pass down 'null' as acceptedDocs, because nestedDocId is a doc to be fetched and
303
+ // therefore is guaranteed to be a live doc.
304
+ BitSet nestedDocIds = sc .bitsetFilterCache ().getBitSetProducer (filter ).getBitSet (context );
305
+ if (nestedDocIds != null && nestedDocIds .get (nestedDocId )) {
306
+ return true ;
307
+ } else {
308
+ return false ;
309
+ }
310
+ }
311
+
304
312
public DocumentMapper merge (Mapping mapping , MergeReason reason ) {
305
313
Mapping merged = this .mapping .merge (mapping , reason );
306
314
return new DocumentMapper (mapperService , merged );
0 commit comments