2020import org .elasticsearch .common .Explicit ;
2121import org .elasticsearch .common .settings .Settings ;
2222import org .elasticsearch .index .IndexMode ;
23+ import org .elasticsearch .index .IndexVersion ;
24+ import org .elasticsearch .index .IndexVersions ;
2325import org .elasticsearch .index .fielddata .FieldDataContext ;
2426import org .elasticsearch .index .fielddata .IndexFieldData ;
2527import org .elasticsearch .index .fielddata .IndexNumericFieldData ;
2628import org .elasticsearch .index .fielddata .plain .SortedNumericIndexFieldData ;
2729import org .elasticsearch .index .mapper .BlockDocValuesReader ;
2830import org .elasticsearch .index .mapper .BlockLoader ;
2931import org .elasticsearch .index .mapper .BlockSourceReader ;
32+ import org .elasticsearch .index .mapper .CompositeSyntheticFieldLoader ;
3033import org .elasticsearch .index .mapper .DocumentParserContext ;
3134import org .elasticsearch .index .mapper .FallbackSyntheticSourceBlockLoader ;
3235import org .elasticsearch .index .mapper .FieldMapper ;
3740import org .elasticsearch .index .mapper .MappingLookup ;
3841import org .elasticsearch .index .mapper .SimpleMappedFieldType ;
3942import org .elasticsearch .index .mapper .SortedNumericDocValuesSyntheticFieldLoader ;
43+ import org .elasticsearch .index .mapper .SortedNumericWithOffsetsDocValuesSyntheticFieldLoaderLayer ;
44+ import org .elasticsearch .index .mapper .SourceLoader ;
4045import org .elasticsearch .index .mapper .SourceValueFetcher ;
4146import org .elasticsearch .index .mapper .TextSearchInfo ;
4247import org .elasticsearch .index .mapper .TimeSeriesParams ;
6469import java .util .Set ;
6570import java .util .function .Function ;
6671
72+ import static org .elasticsearch .index .mapper .FieldArrayContext .getOffsetsFieldName ;
6773import static org .elasticsearch .xpack .unsignedlong .UnsignedLongLeafFieldData .convertUnsignedLongToDouble ;
6874
6975public class UnsignedLongFieldMapper extends FieldMapper {
@@ -97,13 +103,27 @@ public static final class Builder extends FieldMapper.DimensionBuilder {
97103 */
98104 private final Parameter <MetricType > metric ;
99105
106+ private final IndexVersion indexCreatedVersion ;
100107 private final IndexMode indexMode ;
108+ private final SourceKeepMode indexSourceKeepMode ;
101109
102- public Builder (String name , Settings settings , IndexMode mode ) {
103- this (name , IGNORE_MALFORMED_SETTING .get (settings ), mode );
110+ public Builder (
111+ String name ,
112+ Settings settings ,
113+ IndexVersion indexCreatedVersion ,
114+ IndexMode mode ,
115+ SourceKeepMode indexSourceKeepMode
116+ ) {
117+ this (name , IGNORE_MALFORMED_SETTING .get (settings ), indexCreatedVersion , mode , indexSourceKeepMode );
104118 }
105119
106- public Builder (String name , boolean ignoreMalformedByDefault , IndexMode mode ) {
120+ public Builder (
121+ String name ,
122+ boolean ignoreMalformedByDefault ,
123+ IndexVersion indexCreatedVersion ,
124+ IndexMode mode ,
125+ SourceKeepMode indexSourceKeepMode
126+ ) {
107127 super (name );
108128 this .ignoreMalformed = Parameter .explicitBoolParam (
109129 "ignore_malformed" ,
@@ -150,6 +170,9 @@ public Builder(String name, boolean ignoreMalformedByDefault, IndexMode mode) {
150170 );
151171 }
152172 }).precludesParameters (dimension );
173+
174+ this .indexCreatedVersion = indexCreatedVersion ;
175+ this .indexSourceKeepMode = indexSourceKeepMode ;
153176 }
154177
155178 private String parseNullValueAsString (Object o ) {
@@ -211,11 +234,35 @@ public UnsignedLongFieldMapper build(MapperBuilderContext context) {
211234 indexMode ,
212235 context .isSourceSynthetic ()
213236 );
214- return new UnsignedLongFieldMapper (leafName (), fieldType , builderParams (this , context ), context .isSourceSynthetic (), this );
237+ String offsetsFieldName = getOffsetsFieldName (
238+ context ,
239+ indexSourceKeepMode ,
240+ hasDocValues .getValue (),
241+ stored .getValue (),
242+ this ,
243+ indexCreatedVersion ,
244+ IndexVersions .SYNTHETIC_SOURCE_STORE_ARRAYS_NATIVELY
245+ );
246+ return new UnsignedLongFieldMapper (
247+ leafName (),
248+ fieldType ,
249+ builderParams (this , context ),
250+ context .isSourceSynthetic (),
251+ this ,
252+ offsetsFieldName
253+ );
215254 }
216255 }
217256
218- public static final TypeParser PARSER = new TypeParser ((n , c ) -> new Builder (n , c .getSettings (), c .getIndexSettings ().getMode ()));
257+ public static final TypeParser PARSER = new TypeParser (
258+ (n , c ) -> new Builder (
259+ n ,
260+ c .getSettings (),
261+ c .indexVersionCreated (),
262+ c .getIndexSettings ().getMode (),
263+ c .getIndexSettings ().sourceKeepMode ()
264+ )
265+ );
219266
220267 public static final class UnsignedLongFieldType extends SimpleMappedFieldType {
221268
@@ -640,14 +687,18 @@ public MetricType getMetricType() {
640687 private final Long nullValueIndexed ; // null value to use for indexing, represented as shifted to signed long range
641688 private final boolean dimension ;
642689 private final MetricType metricType ;
690+ private final IndexVersion indexCreatedVersion ;
643691 private final IndexMode indexMode ;
692+ private final String offsetsFieldName ;
693+ private final SourceKeepMode indexSourceKeepMode ;
644694
645695 private UnsignedLongFieldMapper (
646696 String simpleName ,
647697 MappedFieldType mappedFieldType ,
648698 BuilderParams builderParams ,
649699 boolean isSourceSynthetic ,
650- Builder builder
700+ Builder builder ,
701+ String offsetsFieldName
651702 ) {
652703 super (simpleName , mappedFieldType , builderParams );
653704 this .isSourceSynthetic = isSourceSynthetic ;
@@ -666,6 +717,9 @@ private UnsignedLongFieldMapper(
666717 this .dimension = builder .dimension .getValue ();
667718 this .metricType = builder .metric .getValue ();
668719 this .indexMode = builder .indexMode ;
720+ this .indexCreatedVersion = builder .indexCreatedVersion ;
721+ this .offsetsFieldName = offsetsFieldName ;
722+ this .indexSourceKeepMode = builder .indexSourceKeepMode ;
669723 }
670724
671725 @ Override
@@ -678,6 +732,11 @@ public UnsignedLongFieldType fieldType() {
678732 return (UnsignedLongFieldType ) super .fieldType ();
679733 }
680734
735+ @ Override
736+ public String getOffsetFieldName () {
737+ return offsetsFieldName ;
738+ }
739+
681740 @ Override
682741 protected String contentType () {
683742 return CONTENT_TYPE ;
@@ -714,7 +773,6 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
714773 boolean isNullValue = false ;
715774 if (numericValue == null ) {
716775 numericValue = nullValueIndexed ;
717- if (numericValue == null ) return ;
718776 isNullValue = true ;
719777 } else {
720778 numericValue = unsignedToSortableSignedLong (numericValue );
@@ -724,29 +782,41 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
724782 context .getRoutingFields ().addUnsignedLong (fieldType ().name (), numericValue );
725783 }
726784
727- List <Field > fields = new ArrayList <>();
728- if (indexed && hasDocValues ) {
729- fields .add (new LongField (fieldType ().name (), numericValue ));
730- } else if (hasDocValues ) {
731- fields .add (new SortedNumericDocValuesField (fieldType ().name (), numericValue ));
732- } else if (indexed ) {
733- fields .add (new LongPoint (fieldType ().name (), numericValue ));
734- }
735- if (stored ) {
736- // for stored field, keeping original unsigned_long value in the String form
737- String storedValued = isNullValue ? nullValue : Long .toUnsignedString (unsignedToSortableSignedLong (numericValue ));
738- fields .add (new StoredField (fieldType ().name (), storedValued ));
785+ if (numericValue != null ) {
786+ List <Field > fields = new ArrayList <>();
787+ if (indexed && hasDocValues ) {
788+ fields .add (new LongField (fieldType ().name (), numericValue ));
789+ } else if (hasDocValues ) {
790+ fields .add (new SortedNumericDocValuesField (fieldType ().name (), numericValue ));
791+ } else if (indexed ) {
792+ fields .add (new LongPoint (fieldType ().name (), numericValue ));
793+ }
794+ if (stored ) {
795+ // for stored field, keeping original unsigned_long value in the String form
796+ String storedValued = isNullValue ? nullValue : Long .toUnsignedString (unsignedToSortableSignedLong (numericValue ));
797+ fields .add (new StoredField (fieldType ().name (), storedValued ));
798+ }
799+ context .doc ().addAll (fields );
800+
801+ if (hasDocValues == false && (stored || indexed )) {
802+ context .addToFieldNames (fieldType ().name ());
803+ }
739804 }
740- context .doc ().addAll (fields );
741805
742- if (hasDocValues == false && (stored || indexed )) {
743- context .addToFieldNames (fieldType ().name ());
806+ if (offsetsFieldName != null && context .isImmediateParentAnArray () && context .canAddIgnoredField ()) {
807+ if (numericValue != null ) {
808+ context .getOffSetContext ().recordOffset (offsetsFieldName , numericValue );
809+ } else {
810+ context .getOffSetContext ().recordNull (offsetsFieldName );
811+ }
744812 }
745813 }
746814
747815 @ Override
748816 public FieldMapper .Builder getMergeBuilder () {
749- return new Builder (leafName (), ignoreMalformedByDefault , indexMode ).dimension (dimension ).metric (metricType ).init (this );
817+ return new Builder (leafName (), ignoreMalformedByDefault , indexCreatedVersion , indexMode , indexSourceKeepMode ).dimension (dimension )
818+ .metric (metricType )
819+ .init (this );
750820 }
751821
752822 /**
@@ -827,17 +897,34 @@ public void doValidate(MappingLookup lookup) {
827897 }
828898 }
829899
900+ private SourceLoader .SyntheticFieldLoader docValuesSyntheticFieldLoader () {
901+ if (offsetsFieldName != null ) {
902+ var layers = new ArrayList <CompositeSyntheticFieldLoader .Layer >(2 );
903+ layers .add (
904+ new SortedNumericWithOffsetsDocValuesSyntheticFieldLoaderLayer (
905+ fullPath (),
906+ offsetsFieldName ,
907+ (b , value ) -> b .value (DocValueFormat .UNSIGNED_LONG_SHIFTED .format (value ))
908+ )
909+ );
910+ if (ignoreMalformed .value ()) {
911+ layers .add (new CompositeSyntheticFieldLoader .MalformedValuesLayer (fullPath ()));
912+ }
913+ return new CompositeSyntheticFieldLoader (leafName (), fullPath (), layers );
914+ } else {
915+ return new SortedNumericDocValuesSyntheticFieldLoader (fullPath (), leafName (), ignoreMalformed ()) {
916+ @ Override
917+ protected void writeValue (XContentBuilder b , long value ) throws IOException {
918+ b .value (DocValueFormat .UNSIGNED_LONG_SHIFTED .format (value ));
919+ }
920+ };
921+ }
922+ }
923+
830924 @ Override
831925 protected SyntheticSourceSupport syntheticSourceSupport () {
832926 if (hasDocValues ) {
833- return new SyntheticSourceSupport .Native (
834- () -> new SortedNumericDocValuesSyntheticFieldLoader (fullPath (), leafName (), ignoreMalformed ()) {
835- @ Override
836- protected void writeValue (XContentBuilder b , long value ) throws IOException {
837- b .value (DocValueFormat .UNSIGNED_LONG_SHIFTED .format (value ));
838- }
839- }
840- );
927+ return new SyntheticSourceSupport .Native (this ::docValuesSyntheticFieldLoader );
841928 }
842929
843930 return super .syntheticSourceSupport ();
0 commit comments