3535import  org .elasticsearch .common .text .UTF8DecodingReader ;
3636import  org .elasticsearch .common .unit .Fuzziness ;
3737import  org .elasticsearch .index .IndexVersion ;
38+ import  org .elasticsearch .index .IndexVersions ;
3839import  org .elasticsearch .index .analysis .IndexAnalyzers ;
3940import  org .elasticsearch .index .analysis .NamedAnalyzer ;
4041import  org .elasticsearch .index .fielddata .FieldDataContext ;
@@ -105,8 +106,15 @@ public static class Builder extends FieldMapper.Builder {
105106
106107        private  final  TextParams .Analyzers  analyzers ;
107108        private  final  boolean  withinMultiField ;
109+         private  final  boolean  storedFieldInBinaryFormat ;
108110
109-         public  Builder (String  name , IndexVersion  indexCreatedVersion , IndexAnalyzers  indexAnalyzers , boolean  withinMultiField ) {
111+         public  Builder (
112+             String  name ,
113+             IndexVersion  indexCreatedVersion ,
114+             IndexAnalyzers  indexAnalyzers ,
115+             boolean  withinMultiField ,
116+             boolean  storedFieldInBinaryFormat 
117+         ) {
110118            super (name );
111119            this .indexCreatedVersion  = indexCreatedVersion ;
112120            this .analyzers  = new  TextParams .Analyzers (
@@ -116,6 +124,7 @@ public Builder(String name, IndexVersion indexCreatedVersion, IndexAnalyzers ind
116124                indexCreatedVersion 
117125            );
118126            this .withinMultiField  = withinMultiField ;
127+             this .storedFieldInBinaryFormat  = storedFieldInBinaryFormat ;
119128        }
120129
121130        @ Override 
@@ -135,7 +144,8 @@ private MatchOnlyTextFieldType buildFieldType(MapperBuilderContext context) {
135144                context .isSourceSynthetic (),
136145                meta .getValue (),
137146                withinMultiField ,
138-                 multiFieldsBuilder .hasSyntheticSourceCompatibleKeywordField ()
147+                 multiFieldsBuilder .hasSyntheticSourceCompatibleKeywordField (),
148+                 storedFieldInBinaryFormat 
139149            );
140150            return  ft ;
141151        }
@@ -155,8 +165,22 @@ public MatchOnlyTextFieldMapper build(MapperBuilderContext context) {
155165        }
156166    }
157167
168+     private  static  boolean  isSyntheticSourceStoredFieldInBinaryFormat (IndexVersion  indexCreatedVersion ) {
169+         return  indexCreatedVersion .onOrAfter (IndexVersions .MATCH_ONLY_TEXT_STORED_AS_BYTES )
170+             || indexCreatedVersion .between (
171+                 IndexVersions .MATCH_ONLY_TEXT_STORED_AS_BYTES_BACKPORT_8_X ,
172+                 IndexVersions .UPGRADE_TO_LUCENE_10_0_0 
173+             );
174+     }
175+ 
158176    public  static  final  TypeParser  PARSER  = new  TypeParser (
159-         (n , c ) -> new  Builder (n , c .indexVersionCreated (), c .getIndexAnalyzers (), c .isWithinMultiField ())
177+         (n , c ) -> new  Builder (
178+             n ,
179+             c .indexVersionCreated (),
180+             c .getIndexAnalyzers (),
181+             c .isWithinMultiField (),
182+             isSyntheticSourceStoredFieldInBinaryFormat (c .indexVersionCreated ())
183+         )
160184    );
161185
162186    public  static  class  MatchOnlyTextFieldType  extends  StringFieldType  {
@@ -167,6 +191,7 @@ public static class MatchOnlyTextFieldType extends StringFieldType {
167191
168192        private  final  boolean  withinMultiField ;
169193        private  final  boolean  hasCompatibleMultiFields ;
194+         private  final  boolean  storedFieldInBinaryFormat ;
170195
171196        public  MatchOnlyTextFieldType (
172197            String  name ,
@@ -175,14 +200,16 @@ public MatchOnlyTextFieldType(
175200            boolean  isSyntheticSource ,
176201            Map <String , String > meta ,
177202            boolean  withinMultiField ,
178-             boolean  hasCompatibleMultiFields 
203+             boolean  hasCompatibleMultiFields ,
204+             boolean  storedFieldInBinaryFormat 
179205        ) {
180206            super (name , true , false , false , tsi , meta );
181207            this .indexAnalyzer  = Objects .requireNonNull (indexAnalyzer );
182208            this .textFieldType  = new  TextFieldType (name , isSyntheticSource );
183209            this .originalName  = isSyntheticSource  ? name  + "._original"  : null ;
184210            this .withinMultiField  = withinMultiField ;
185211            this .hasCompatibleMultiFields  = hasCompatibleMultiFields ;
212+             this .storedFieldInBinaryFormat  = storedFieldInBinaryFormat ;
186213        }
187214
188215        public  MatchOnlyTextFieldType (String  name ) {
@@ -193,6 +220,7 @@ public MatchOnlyTextFieldType(String name) {
193220                false ,
194221                Collections .emptyMap (),
195222                false ,
223+                 false ,
196224                false 
197225            );
198226        }
@@ -451,7 +479,11 @@ protected BytesRef toBytesRef(Object v) {
451479        @ Override 
452480        public  BlockLoader  blockLoader (BlockLoaderContext  blContext ) {
453481            if  (textFieldType .isSyntheticSource ()) {
454-                 return  new  BytesFromMixedStringsBytesRefBlockLoader (storedFieldNameForSyntheticSource ());
482+                 if  (storedFieldInBinaryFormat ) {
483+                     return  new  BlockStoredFieldsReader .BytesFromBytesRefsBlockLoader (storedFieldNameForSyntheticSource ());
484+                 } else  {
485+                     return  new  BytesFromMixedStringsBytesRefBlockLoader (storedFieldNameForSyntheticSource ());
486+                 }
455487            }
456488            SourceValueFetcher  fetcher  = SourceValueFetcher .toString (blContext .sourcePaths (name ()));
457489            // MatchOnlyText never has norms, so we have to use the field names field 
@@ -502,6 +534,7 @@ private String storedFieldNameForSyntheticSource() {
502534    private  final  boolean  storeSource ;
503535    private  final  FieldType  fieldType ;
504536    private  final  boolean  withinMultiField ;
537+     private  final  boolean  storedFieldInBinaryFormat ;
505538
506539    private  MatchOnlyTextFieldMapper (
507540        String  simpleName ,
@@ -521,6 +554,7 @@ private MatchOnlyTextFieldMapper(
521554        this .positionIncrementGap  = builder .analyzers .positionIncrementGap .getValue ();
522555        this .storeSource  = storeSource ;
523556        this .withinMultiField  = builder .withinMultiField ;
557+         this .storedFieldInBinaryFormat  = builder .storedFieldInBinaryFormat ;
524558    }
525559
526560    @ Override 
@@ -530,7 +564,7 @@ public Map<String, NamedAnalyzer> indexAnalyzers() {
530564
531565    @ Override 
532566    public  FieldMapper .Builder  getMergeBuilder () {
533-         return  new  Builder (leafName (), indexCreatedVersion , indexAnalyzers , withinMultiField ).init (this );
567+         return  new  Builder (leafName (), indexCreatedVersion , indexAnalyzers , withinMultiField ,  storedFieldInBinaryFormat ).init (this );
534568    }
535569
536570    @ Override 
@@ -547,8 +581,12 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
547581        context .addToFieldNames (fieldType ().name ());
548582
549583        if  (storeSource ) {
550-             final  var  bytesRef  = new  BytesRef (utfBytes .bytes (), utfBytes .offset (), utfBytes .length ());
551-             context .doc ().add (new  StoredField (fieldType ().storedFieldNameForSyntheticSource (), bytesRef ));
584+             if  (storedFieldInBinaryFormat ) {
585+                 final  var  bytesRef  = new  BytesRef (utfBytes .bytes (), utfBytes .offset (), utfBytes .length ());
586+                 context .doc ().add (new  StoredField (fieldType ().storedFieldNameForSyntheticSource (), bytesRef ));
587+             } else  {
588+                 context .doc ().add (new  StoredField (fieldType ().storedFieldNameForSyntheticSource (), value .string ()));
589+             }
552590        }
553591    }
554592
0 commit comments