1414import org .apache .lucene .document .Field ;
1515import org .apache .lucene .document .FieldType ;
1616import org .apache .lucene .document .StoredField ;
17- import org .apache .lucene .index .BinaryDocValues ;
18- import org .apache .lucene .index .DocValues ;
1917import org .apache .lucene .index .IndexOptions ;
2018import org .apache .lucene .index .LeafReaderContext ;
2119import org .apache .lucene .index .Term ;
3230import org .apache .lucene .util .BytesRef ;
3331import org .apache .lucene .util .IOFunction ;
3432import org .elasticsearch .common .CheckedIntFunction ;
35- import org .elasticsearch .common .io .stream .ByteArrayStreamInput ;
3633import org .elasticsearch .common .lucene .Lucene ;
3734import org .elasticsearch .common .text .UTF8DecodingReader ;
3835import org .elasticsearch .common .unit .Fuzziness ;
4239import org .elasticsearch .index .analysis .NamedAnalyzer ;
4340import org .elasticsearch .index .fielddata .FieldDataContext ;
4441import org .elasticsearch .index .fielddata .IndexFieldData ;
45- import org .elasticsearch .index .fielddata .SortedBinaryDocValues ;
4642import org .elasticsearch .index .fielddata .SourceValueFetcherSortedBinaryIndexFieldData ;
4743import org .elasticsearch .index .fielddata .StoredFieldSortedBinaryIndexFieldData ;
4844import org .elasticsearch .index .fieldvisitor .StoredFieldLoader ;
@@ -301,17 +297,12 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
301297
302298 if (parent instanceof KeywordFieldMapper .KeywordFieldType keywordParent
303299 && keywordParent .ignoreAbove ().valuesPotentiallyIgnored ()) {
300+ final String parentFallbackFieldName = keywordParent .syntheticSourceFallbackFieldName ();
304301 if (parent .isStored ()) {
305- return combineFieldFetchers (
306- storedFieldFetcher (parentFieldName ),
307- ignoredValuesDocValuesFieldFetcher (keywordParent .syntheticSourceFallbackFieldName ())
308- );
302+ return storedFieldFetcher (parentFieldName , parentFallbackFieldName );
309303 } else if (parent .hasDocValues ()) {
310304 var ifd = searchExecutionContext .getForField (parent , MappedFieldType .FielddataOperation .SEARCH );
311- return combineFieldFetchers (
312- docValuesFieldFetcher (ifd ),
313- ignoredValuesDocValuesFieldFetcher (keywordParent .syntheticSourceFallbackFieldName ())
314- );
305+ return combineFieldFetchers (docValuesFieldFetcher (ifd ), storedFieldFetcher (parentFallbackFieldName ));
315306 }
316307 }
317308
@@ -334,16 +325,22 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
334325 final KeywordFieldMapper .KeywordFieldType keywordDelegate
335326 ) {
336327 if (keywordDelegate .ignoreAbove ().valuesPotentiallyIgnored ()) {
337- String delegateFieldName = keywordDelegate .name ();
338- // bc we don't know whether the delegate will ignore a value, we must also check the fallback field created by this
339- // match_only_text field
328+ // because we don't know whether the delegate field will be ignored during parsing, we must also check the current field
329+ String fieldName = name ();
340330 String fallbackName = syntheticSourceFallbackFieldName ();
341331
332+ // delegate field names
333+ String delegateFieldName = keywordDelegate .name ();
334+ String delegateFieldFallbackName = keywordDelegate .syntheticSourceFallbackFieldName ();
335+
342336 if (keywordDelegate .isStored ()) {
343- return storedFieldFetcher (delegateFieldName , fallbackName );
337+ return storedFieldFetcher (delegateFieldName , delegateFieldFallbackName , fieldName , fallbackName );
344338 } else if (keywordDelegate .hasDocValues ()) {
345339 var ifd = searchExecutionContext .getForField (keywordDelegate , MappedFieldType .FielddataOperation .SEARCH );
346- return combineFieldFetchers (docValuesFieldFetcher (ifd ), storedFieldFetcher (fallbackName ));
340+ return combineFieldFetchers (
341+ docValuesFieldFetcher (ifd ),
342+ storedFieldFetcher (delegateFieldFallbackName , fieldName , fallbackName )
343+ );
347344 }
348345 }
349346
@@ -358,34 +355,25 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
358355 }
359356 }
360357
361- private IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> docValuesFieldFetcher (IndexFieldData <?> ifd ) {
362- return context -> {
363- SortedBinaryDocValues indexedValuesDocValues = ifd .load (context ).getBytesValues ();
364- return docId -> getValuesFromDocValues (indexedValuesDocValues , docId );
365- };
366- }
367-
368- private IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> ignoredValuesDocValuesFieldFetcher (
369- String fieldName
358+ private static IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> docValuesFieldFetcher (
359+ IndexFieldData <?> ifd
370360 ) {
371361 return context -> {
372- CustomBinaryDocValues ignoredValuesDocValues = new CustomBinaryDocValues (DocValues .getBinary (context .reader (), fieldName ));
373- return docId -> getValuesFromDocValues (ignoredValuesDocValues , docId );
362+ var sortedBinaryDocValues = ifd .load (context ).getBytesValues ();
363+ return docId -> {
364+ if (sortedBinaryDocValues .advanceExact (docId )) {
365+ var values = new ArrayList <>(sortedBinaryDocValues .docValueCount ());
366+ for (int i = 0 ; i < sortedBinaryDocValues .docValueCount (); i ++) {
367+ values .add (sortedBinaryDocValues .nextValue ().utf8ToString ());
368+ }
369+ return values ;
370+ } else {
371+ return List .of ();
372+ }
373+ };
374374 };
375375 }
376376
377- private List <Object > getValuesFromDocValues (SortedBinaryDocValues docValues , int docId ) throws IOException {
378- if (docValues .advanceExact (docId )) {
379- var values = new ArrayList <>(docValues .docValueCount ());
380- for (int i = 0 ; i < docValues .docValueCount (); i ++) {
381- values .add (docValues .nextValue ().utf8ToString ());
382- }
383- return values ;
384- } else {
385- return List .of ();
386- }
387- }
388-
389377 private static IOFunction <LeafReaderContext , CheckedIntFunction <List <Object >, IOException >> storedFieldFetcher (String ... names ) {
390378 var loader = StoredFieldLoader .create (false , Set .of (names ));
391379 return context -> {
@@ -791,46 +779,4 @@ protected void writeValue(Object value, XContentBuilder b) throws IOException {
791779
792780 return fieldLoader ;
793781 }
794-
795- /**
796- * A wrapper around {@link BinaryDocValues} that exposes some quality of life functions. Note, these values are not sorted.
797- */
798- private static class CustomBinaryDocValues extends SortedBinaryDocValues {
799-
800- private final BinaryDocValues binaryDocValues ;
801- private final ByteArrayStreamInput stream ;
802-
803- private int docValueCount = 0 ;
804-
805- CustomBinaryDocValues (BinaryDocValues binaryDocValues ) {
806- this .binaryDocValues = binaryDocValues ;
807- this .stream = new ByteArrayStreamInput ();
808- }
809-
810- @ Override
811- public BytesRef nextValue () throws IOException {
812- // this function already knows how to decode the underlying bytes array, so no need to explicitly call VInt()
813- return stream .readBytesRef ();
814- }
815-
816- @ Override
817- public boolean advanceExact (int docId ) throws IOException {
818- // if document has a value, read underlying bytes
819- if (binaryDocValues .advanceExact (docId )) {
820- BytesRef docValuesBytes = binaryDocValues .binaryValue ();
821- stream .reset (docValuesBytes .bytes , docValuesBytes .offset , docValuesBytes .length );
822- docValueCount = stream .readVInt ();
823- return true ;
824- }
825-
826- // otherwise there is nothing to do
827- docValueCount = 0 ;
828- return false ;
829- }
830-
831- @ Override
832- public int docValueCount () {
833- return docValueCount ;
834- }
835- }
836782}
0 commit comments