1919import org .elasticsearch .common .settings .Settings ;
2020import org .elasticsearch .common .xcontent .support .XContentMapValues ;
2121import org .elasticsearch .index .IndexMode ;
22+ import org .elasticsearch .index .IndexVersion ;
23+ import org .elasticsearch .index .IndexVersions ;
2224import org .elasticsearch .index .fielddata .FieldData ;
2325import org .elasticsearch .index .fielddata .FieldDataContext ;
2426import org .elasticsearch .index .fielddata .IndexFieldData ;
3234import org .elasticsearch .index .mapper .BlockDocValuesReader ;
3335import org .elasticsearch .index .mapper .BlockLoader ;
3436import org .elasticsearch .index .mapper .BlockSourceReader ;
37+ import org .elasticsearch .index .mapper .CompositeSyntheticFieldLoader ;
3538import org .elasticsearch .index .mapper .DocumentParserContext ;
3639import org .elasticsearch .index .mapper .FallbackSyntheticSourceBlockLoader ;
3740import org .elasticsearch .index .mapper .FieldMapper ;
4043import org .elasticsearch .index .mapper .NumberFieldMapper ;
4144import org .elasticsearch .index .mapper .SimpleMappedFieldType ;
4245import org .elasticsearch .index .mapper .SortedNumericDocValuesSyntheticFieldLoader ;
46+ import org .elasticsearch .index .mapper .SortedNumericWithOffsetsDocValuesSyntheticFieldLoaderLayer ;
47+ import org .elasticsearch .index .mapper .SourceLoader ;
4348import org .elasticsearch .index .mapper .SourceValueFetcher ;
4449import org .elasticsearch .index .mapper .TextSearchInfo ;
4550import org .elasticsearch .index .mapper .TimeSeriesParams ;
6772import java .util .Objects ;
6873import java .util .Set ;
6974
75+ import static org .elasticsearch .index .mapper .FieldArrayContext .getOffsetsFieldName ;
76+
7077/** A {@link FieldMapper} for scaled floats. Values are internally multiplied
7178 * by a scaling factor and rounded to the closest long. */
7279public class ScaledFloatFieldMapper extends FieldMapper {
@@ -125,12 +132,34 @@ public static class Builder extends FieldMapper.Builder {
125132 private final Parameter <TimeSeriesParams .MetricType > metric ;
126133
127134 private final IndexMode indexMode ;
135+ private final IndexVersion indexCreatedVersion ;
136+ private final SourceKeepMode indexSourceKeepMode ;
128137
129- public Builder (String name , Settings settings , IndexMode indexMode ) {
130- this (name , IGNORE_MALFORMED_SETTING .get (settings ), COERCE_SETTING .get (settings ), indexMode );
138+ public Builder (
139+ String name ,
140+ Settings settings ,
141+ IndexMode indexMode ,
142+ IndexVersion indexCreatedVersion ,
143+ SourceKeepMode indexSourceKeepMode
144+ ) {
145+ this (
146+ name ,
147+ IGNORE_MALFORMED_SETTING .get (settings ),
148+ COERCE_SETTING .get (settings ),
149+ indexMode ,
150+ indexCreatedVersion ,
151+ indexSourceKeepMode
152+ );
131153 }
132154
133- public Builder (String name , boolean ignoreMalformedByDefault , boolean coerceByDefault , IndexMode indexMode ) {
155+ public Builder (
156+ String name ,
157+ boolean ignoreMalformedByDefault ,
158+ boolean coerceByDefault ,
159+ IndexMode indexMode ,
160+ IndexVersion indexCreatedVersion ,
161+ SourceKeepMode indexSourceKeepMode
162+ ) {
134163 super (name );
135164 this .ignoreMalformed = Parameter .explicitBoolParam (
136165 "ignore_malformed" ,
@@ -159,6 +188,8 @@ public Builder(String name, boolean ignoreMalformedByDefault, boolean coerceByDe
159188 );
160189 }
161190 });
191+ this .indexCreatedVersion = indexCreatedVersion ;
192+ this .indexSourceKeepMode = indexSourceKeepMode ;
162193 }
163194
164195 Builder scalingFactor (double scalingFactor ) {
@@ -200,11 +231,35 @@ public ScaledFloatFieldMapper build(MapperBuilderContext context) {
200231 coerce .getValue ().value (),
201232 context .isSourceSynthetic ()
202233 );
203- return new ScaledFloatFieldMapper (leafName (), type , builderParams (this , context ), context .isSourceSynthetic (), this );
234+ String offsetsFieldName = getOffsetsFieldName (
235+ context ,
236+ indexSourceKeepMode ,
237+ hasDocValues .getValue (),
238+ stored .getValue (),
239+ this ,
240+ indexCreatedVersion ,
241+ IndexVersions .SYNTHETIC_SOURCE_STORE_ARRAYS_NATIVELY
242+ );
243+ return new ScaledFloatFieldMapper (
244+ leafName (),
245+ type ,
246+ builderParams (this , context ),
247+ context .isSourceSynthetic (),
248+ this ,
249+ offsetsFieldName
250+ );
204251 }
205252 }
206253
207- public static final TypeParser PARSER = new TypeParser ((n , c ) -> new Builder (n , c .getSettings (), c .getIndexSettings ().getMode ()));
254+ public static final TypeParser PARSER = new TypeParser (
255+ (n , c ) -> new Builder (
256+ n ,
257+ c .getSettings (),
258+ c .getIndexSettings ().getMode (),
259+ c .indexVersionCreated (),
260+ c .getIndexSettings ().sourceKeepMode ()
261+ )
262+ );
208263
209264 public static final class ScaledFloatFieldType extends SimpleMappedFieldType {
210265
@@ -532,12 +587,17 @@ public String toString() {
532587 private final TimeSeriesParams .MetricType metricType ;
533588 private final IndexMode indexMode ;
534589
590+ private final IndexVersion indexCreatedVersion ;
591+ private final String offsetsFieldName ;
592+ private final SourceKeepMode indexSourceKeepMode ;
593+
535594 private ScaledFloatFieldMapper (
536595 String simpleName ,
537596 ScaledFloatFieldType mappedFieldType ,
538597 BuilderParams builderParams ,
539598 boolean isSourceSynthetic ,
540- Builder builder
599+ Builder builder ,
600+ String offsetsFieldName
541601 ) {
542602 super (simpleName , mappedFieldType , builderParams );
543603 this .isSourceSynthetic = isSourceSynthetic ;
@@ -552,6 +612,9 @@ private ScaledFloatFieldMapper(
552612 this .coerceByDefault = builder .coerce .getDefaultValue ().value ();
553613 this .metricType = builder .metric .getValue ();
554614 this .indexMode = builder .indexMode ;
615+ this .indexCreatedVersion = builder .indexCreatedVersion ;
616+ this .offsetsFieldName = offsetsFieldName ;
617+ this .indexSourceKeepMode = builder .indexSourceKeepMode ;
555618 }
556619
557620 boolean coerce () {
@@ -563,6 +626,11 @@ public boolean ignoreMalformed() {
563626 return ignoreMalformed .value ();
564627 }
565628
629+ @ Override
630+ public String getOffsetFieldName () {
631+ return offsetsFieldName ;
632+ }
633+
566634 @ Override
567635 public ScaledFloatFieldType fieldType () {
568636 return (ScaledFloatFieldType ) super .fieldType ();
@@ -575,7 +643,9 @@ protected String contentType() {
575643
576644 @ Override
577645 public FieldMapper .Builder getMergeBuilder () {
578- return new Builder (leafName (), ignoreMalformedByDefault , coerceByDefault , indexMode ).metric (metricType ).init (this );
646+ return new Builder (leafName (), ignoreMalformedByDefault , coerceByDefault , indexMode , indexCreatedVersion , indexSourceKeepMode )
647+ .metric (metricType )
648+ .init (this );
579649 }
580650
581651 @ Override
@@ -605,11 +675,16 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
605675 value = numericValue ;
606676 }
607677
678+ boolean shouldStoreOffsets = offsetsFieldName != null && context .isImmediateParentAnArray () && context .canAddIgnoredField ();
679+
608680 if (value == null ) {
609681 value = nullValue ;
610682 }
611683
612684 if (value == null ) {
685+ if (shouldStoreOffsets ) {
686+ context .getOffSetContext ().recordNull (offsetsFieldName );
687+ }
613688 return ;
614689 }
615690
@@ -635,6 +710,10 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
635710
636711 NumberFieldMapper .NumberType .LONG .addFields (context .doc (), fieldType ().name (), scaledValue , indexed , hasDocValues , stored );
637712
713+ if (shouldStoreOffsets ) {
714+ context .getOffSetContext ().recordOffset (offsetsFieldName , scaledValue );
715+ }
716+
638717 if (hasDocValues == false && (indexed || stored )) {
639718 context .addToFieldNames (fieldType ().name ());
640719 }
@@ -776,17 +855,34 @@ public int docValueCount() {
776855 }
777856 }
778857
858+ private SourceLoader .SyntheticFieldLoader docValuesSyntheticFieldLoader () {
859+ if (offsetsFieldName != null ) {
860+ var layers = new ArrayList <CompositeSyntheticFieldLoader .Layer >(2 );
861+ layers .add (
862+ new SortedNumericWithOffsetsDocValuesSyntheticFieldLoaderLayer (
863+ fullPath (),
864+ offsetsFieldName ,
865+ (b , value ) -> b .value (decodeForSyntheticSource (value , scalingFactor ))
866+ )
867+ );
868+ if (ignoreMalformed .value ()) {
869+ layers .add (new CompositeSyntheticFieldLoader .MalformedValuesLayer (fullPath ()));
870+ }
871+ return new CompositeSyntheticFieldLoader (leafName (), fullPath (), layers );
872+ } else {
873+ return new SortedNumericDocValuesSyntheticFieldLoader (fullPath (), leafName (), ignoreMalformed .value ()) {
874+ @ Override
875+ protected void writeValue (XContentBuilder b , long value ) throws IOException {
876+ b .value (decodeForSyntheticSource (value , scalingFactor ));
877+ }
878+ };
879+ }
880+ }
881+
779882 @ Override
780883 protected SyntheticSourceSupport syntheticSourceSupport () {
781884 if (hasDocValues ) {
782- return new SyntheticSourceSupport .Native (
783- () -> new SortedNumericDocValuesSyntheticFieldLoader (fullPath (), leafName (), ignoreMalformed .value ()) {
784- @ Override
785- protected void writeValue (XContentBuilder b , long value ) throws IOException {
786- b .value (decodeForSyntheticSource (value , scalingFactor ));
787- }
788- }
789- );
885+ return new SyntheticSourceSupport .Native (this ::docValuesSyntheticFieldLoader );
790886 }
791887
792888 return super .syntheticSourceSupport ();
0 commit comments