6767import java .io .IOException ;
6868import java .io .UncheckedIOException ;
6969import java .util .ArrayList ;
70- import java .util .Arrays ;
7170import java .util .Collections ;
7271import java .util .List ;
7372import java .util .Map ;
@@ -253,11 +252,18 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
253252 if (searchExecutionContext .isSourceSynthetic () && withinMultiField ) {
254253 String parentField = searchExecutionContext .parentPath (name ());
255254 var parent = searchExecutionContext .lookup ().fieldType (parentField );
256- if (parent .isStored ()) {
257- if (parent instanceof KeywordFieldMapper .KeywordFieldType keywordParent
258- && keywordParent .ignoreAbove () != Integer .MAX_VALUE ) {
255+
256+ if (parent instanceof KeywordFieldMapper .KeywordFieldType keywordParent
257+ && keywordParent .ignoreAbove () != Integer .MAX_VALUE ) {
258+ if (parent .isStored ()) {
259259 return storedFieldFetcher (parentField , keywordParent .originalName ());
260+ } else if (parent .hasDocValues ()) {
261+ var ifd = searchExecutionContext .getForField (parent , MappedFieldType .FielddataOperation .SEARCH );
262+ return combineFieldFetchers (docValuesFieldFetcher (ifd ), storedFieldFetcher (keywordParent .originalName ()));
260263 }
264+ }
265+
266+ if (parent .isStored ()) {
261267 return storedFieldFetcher (parentField );
262268 } else if (parent .hasDocValues ()) {
263269 var ifd = searchExecutionContext .getForField (parent , MappedFieldType .FielddataOperation .SEARCH );
@@ -268,14 +274,21 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
268274 } else if (searchExecutionContext .isSourceSynthetic () && hasCompatibleMultiFields ) {
269275 var mapper = (MatchOnlyTextFieldMapper ) searchExecutionContext .getMappingLookup ().getMapper (name ());
270276 var kwd = TextFieldMapper .SyntheticSourceHelper .getKeywordFieldMapperForSyntheticSource (mapper );
277+
271278 if (kwd != null ) {
272279 var fieldType = kwd .fieldType ();
273- if (fieldType .isStored ()) {
274- if (fieldType .ignoreAbove () != Integer .MAX_VALUE ) {
280+
281+ if (fieldType .ignoreAbove () != Integer .MAX_VALUE ) {
282+ if (fieldType .isStored ()) {
275283 return storedFieldFetcher (fieldType .name (), fieldType .originalName ());
276- } else {
277- return storedFieldFetcher (fieldType .name ());
284+ } else if (fieldType .hasDocValues ()) {
285+ var ifd = searchExecutionContext .getForField (fieldType , MappedFieldType .FielddataOperation .SEARCH );
286+ return combineFieldFetchers (docValuesFieldFetcher (ifd ), storedFieldFetcher (fieldType .originalName ()));
278287 }
288+ }
289+
290+ if (fieldType .isStored ()) {
291+ return storedFieldFetcher (fieldType .name ());
279292 } else if (fieldType .hasDocValues ()) {
280293 var ifd = searchExecutionContext .getForField (fieldType , MappedFieldType .FielddataOperation .SEARCH );
281294 return docValuesFieldFetcher (ifd );
@@ -332,7 +345,42 @@ private static IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IO
332345 if (names .length == 1 ) {
333346 return storedFields .get (names [0 ]);
334347 }
335- return Arrays .stream (names ).map (storedFields ::get ).filter (Objects ::nonNull ).flatMap (List ::stream ).toList ();
348+
349+ List <Object > values = new ArrayList <>();
350+ for (var name : names ) {
351+ var currValues = storedFields .get (name );
352+ if (currValues != null ) {
353+ values .addAll (currValues );
354+ }
355+ }
356+
357+ return values ;
358+ };
359+ };
360+ }
361+
362+ private static IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> combineFieldFetchers (
363+ IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> primaryFetcher ,
364+ IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> secondaryFetcher
365+ ) {
366+ return context -> {
367+ var primaryGetter = primaryFetcher .apply (context );
368+ var secondaryGetter = secondaryFetcher .apply (context );
369+ return docId -> {
370+ List <Object > values = new ArrayList <>();
371+ var primary = primaryGetter .apply (docId );
372+ if (primary != null ) {
373+ values .addAll (primary );
374+ }
375+
376+ var secondary = secondaryGetter .apply (docId );
377+ if (secondary != null ) {
378+ values .addAll (secondary );
379+ }
380+
381+ assert primary != null || secondary != null ;
382+
383+ return values ;
336384 };
337385 };
338386 }
0 commit comments