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 ;
@@ -247,11 +246,18 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
247246 if (searchExecutionContext .isSourceSynthetic () && withinMultiField ) {
248247 String parentField = searchExecutionContext .parentPath (name ());
249248 var parent = searchExecutionContext .lookup ().fieldType (parentField );
250- if (parent .isStored ()) {
251- if (parent instanceof KeywordFieldMapper .KeywordFieldType keywordParent
252- && keywordParent .ignoreAbove () != Integer .MAX_VALUE ) {
249+
250+ if (parent instanceof KeywordFieldMapper .KeywordFieldType keywordParent
251+ && keywordParent .ignoreAbove () != Integer .MAX_VALUE ) {
252+ if (parent .isStored ()) {
253253 return storedFieldFetcher (parentField , keywordParent .originalName ());
254+ } else if (parent .hasDocValues ()) {
255+ var ifd = searchExecutionContext .getForField (parent , MappedFieldType .FielddataOperation .SEARCH );
256+ return combineFieldFetchers (docValuesFieldFetcher (ifd ), storedFieldFetcher (keywordParent .originalName ()));
254257 }
258+ }
259+
260+ if (parent .isStored ()) {
255261 return storedFieldFetcher (parentField );
256262 } else if (parent .hasDocValues ()) {
257263 var ifd = searchExecutionContext .getForField (parent , MappedFieldType .FielddataOperation .SEARCH );
@@ -262,14 +268,21 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
262268 } else if (searchExecutionContext .isSourceSynthetic () && hasCompatibleMultiFields ) {
263269 var mapper = (MatchOnlyTextFieldMapper ) searchExecutionContext .getMappingLookup ().getMapper (name ());
264270 var kwd = TextFieldMapper .SyntheticSourceHelper .getKeywordFieldMapperForSyntheticSource (mapper );
271+
265272 if (kwd != null ) {
266273 var fieldType = kwd .fieldType ();
267- if (fieldType .isStored ()) {
268- if (fieldType .ignoreAbove () != Integer .MAX_VALUE ) {
274+
275+ if (fieldType .ignoreAbove () != Integer .MAX_VALUE ) {
276+ if (fieldType .isStored ()) {
269277 return storedFieldFetcher (fieldType .name (), fieldType .originalName ());
270- } else {
271- return storedFieldFetcher (fieldType .name ());
278+ } else if (fieldType .hasDocValues ()) {
279+ var ifd = searchExecutionContext .getForField (fieldType , MappedFieldType .FielddataOperation .SEARCH );
280+ return combineFieldFetchers (docValuesFieldFetcher (ifd ), storedFieldFetcher (fieldType .originalName ()));
272281 }
282+ }
283+
284+ if (fieldType .isStored ()) {
285+ return storedFieldFetcher (fieldType .name ());
273286 } else if (fieldType .hasDocValues ()) {
274287 var ifd = searchExecutionContext .getForField (fieldType , MappedFieldType .FielddataOperation .SEARCH );
275288 return docValuesFieldFetcher (ifd );
@@ -326,7 +339,42 @@ private static IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IO
326339 if (names .length == 1 ) {
327340 return storedFields .get (names [0 ]);
328341 }
329- return Arrays .stream (names ).map (storedFields ::get ).filter (Objects ::nonNull ).flatMap (List ::stream ).toList ();
342+
343+ List <Object > values = new ArrayList <>();
344+ for (var name : names ) {
345+ var currValues = storedFields .get (name );
346+ if (currValues != null ) {
347+ values .addAll (currValues );
348+ }
349+ }
350+
351+ return values ;
352+ };
353+ };
354+ }
355+
356+ private static IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> combineFieldFetchers (
357+ IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> primaryFetcher ,
358+ IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> secondaryFetcher
359+ ) {
360+ return context -> {
361+ var primaryGetter = primaryFetcher .apply (context );
362+ var secondaryGetter = secondaryFetcher .apply (context );
363+ return docId -> {
364+ List <Object > values = new ArrayList <>();
365+ var primary = primaryGetter .apply (docId );
366+ if (primary != null ) {
367+ values .addAll (primary );
368+ }
369+
370+ var secondary = secondaryGetter .apply (docId );
371+ if (secondary != null ) {
372+ values .addAll (secondary );
373+ }
374+
375+ assert primary != null || secondary != null ;
376+
377+ return values ;
330378 };
331379 };
332380 }
0 commit comments