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_SCALED_FLOAT
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
@@ -533,12 +588,17 @@ public String toString() {
533588 private final TimeSeriesParams .MetricType metricType ;
534589 private final IndexMode indexMode ;
535590
591+ private final IndexVersion indexCreatedVersion ;
592+ private final String offsetsFieldName ;
593+ private final SourceKeepMode indexSourceKeepMode ;
594+
536595 private ScaledFloatFieldMapper (
537596 String simpleName ,
538597 ScaledFloatFieldType mappedFieldType ,
539598 BuilderParams builderParams ,
540599 boolean isSourceSynthetic ,
541- Builder builder
600+ Builder builder ,
601+ String offsetsFieldName
542602 ) {
543603 super (simpleName , mappedFieldType , builderParams );
544604 this .isSourceSynthetic = isSourceSynthetic ;
@@ -553,6 +613,9 @@ private ScaledFloatFieldMapper(
553613 this .coerceByDefault = builder .coerce .getDefaultValue ().value ();
554614 this .metricType = builder .metric .getValue ();
555615 this .indexMode = builder .indexMode ;
616+ this .indexCreatedVersion = builder .indexCreatedVersion ;
617+ this .offsetsFieldName = offsetsFieldName ;
618+ this .indexSourceKeepMode = builder .indexSourceKeepMode ;
556619 }
557620
558621 boolean coerce () {
@@ -564,6 +627,11 @@ public boolean ignoreMalformed() {
564627 return ignoreMalformed .value ();
565628 }
566629
630+ @ Override
631+ public String getOffsetFieldName () {
632+ return offsetsFieldName ;
633+ }
634+
567635 @ Override
568636 public ScaledFloatFieldType fieldType () {
569637 return (ScaledFloatFieldType ) super .fieldType ();
@@ -576,7 +644,9 @@ protected String contentType() {
576644
577645 @ Override
578646 public FieldMapper .Builder getMergeBuilder () {
579- return new Builder (leafName (), ignoreMalformedByDefault , coerceByDefault , indexMode ).metric (metricType ).init (this );
647+ return new Builder (leafName (), ignoreMalformedByDefault , coerceByDefault , indexMode , indexCreatedVersion , indexSourceKeepMode )
648+ .metric (metricType )
649+ .init (this );
580650 }
581651
582652 @ Override
@@ -606,11 +676,16 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
606676 value = numericValue ;
607677 }
608678
679+ boolean shouldStoreOffsets = offsetsFieldName != null && context .isImmediateParentAnArray () && context .canAddIgnoredField ();
680+
609681 if (value == null ) {
610682 value = nullValue ;
611683 }
612684
613685 if (value == null ) {
686+ if (shouldStoreOffsets ) {
687+ context .getOffSetContext ().recordNull (offsetsFieldName );
688+ }
614689 return ;
615690 }
616691
@@ -636,6 +711,10 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
636711
637712 NumberFieldMapper .NumberType .LONG .addFields (context .doc (), fieldType ().name (), scaledValue , indexed , hasDocValues , stored );
638713
714+ if (shouldStoreOffsets ) {
715+ context .getOffSetContext ().recordOffset (offsetsFieldName , scaledValue );
716+ }
717+
639718 if (hasDocValues == false && (indexed || stored )) {
640719 context .addToFieldNames (fieldType ().name ());
641720 }
@@ -777,17 +856,34 @@ public int docValueCount() {
777856 }
778857 }
779858
859+ private SourceLoader .SyntheticFieldLoader docValuesSyntheticFieldLoader () {
860+ if (offsetsFieldName != null ) {
861+ var layers = new ArrayList <CompositeSyntheticFieldLoader .Layer >(2 );
862+ layers .add (
863+ new SortedNumericWithOffsetsDocValuesSyntheticFieldLoaderLayer (
864+ fullPath (),
865+ offsetsFieldName ,
866+ (b , value ) -> b .value (decodeForSyntheticSource (value , scalingFactor ))
867+ )
868+ );
869+ if (ignoreMalformed .value ()) {
870+ layers .add (new CompositeSyntheticFieldLoader .MalformedValuesLayer (fullPath ()));
871+ }
872+ return new CompositeSyntheticFieldLoader (leafName (), fullPath (), layers );
873+ } else {
874+ return new SortedNumericDocValuesSyntheticFieldLoader (fullPath (), leafName (), ignoreMalformed .value ()) {
875+ @ Override
876+ protected void writeValue (XContentBuilder b , long value ) throws IOException {
877+ b .value (decodeForSyntheticSource (value , scalingFactor ));
878+ }
879+ };
880+ }
881+ }
882+
780883 @ Override
781884 protected SyntheticSourceSupport syntheticSourceSupport () {
782885 if (hasDocValues ) {
783- return new SyntheticSourceSupport .Native (
784- () -> new SortedNumericDocValuesSyntheticFieldLoader (fullPath (), leafName (), ignoreMalformed .value ()) {
785- @ Override
786- protected void writeValue (XContentBuilder b , long value ) throws IOException {
787- b .value (decodeForSyntheticSource (value , scalingFactor ));
788- }
789- }
790- );
886+ return new SyntheticSourceSupport .Native (this ::docValuesSyntheticFieldLoader );
791887 }
792888
793889 return super .syntheticSourceSupport ();
0 commit comments