19
19
20
20
package org .elasticsearch .index .mapper ;
21
21
22
- import org .apache .lucene .document .FieldType ;
23
- import org .apache .lucene .index .IndexOptions ;
24
22
import org .apache .lucene .index .Term ;
25
23
import org .apache .lucene .search .BoostQuery ;
26
24
import org .apache .lucene .search .DocValuesFieldExistsQuery ;
34
32
import org .elasticsearch .common .lucene .Lucene ;
35
33
import org .elasticsearch .common .network .InetAddresses ;
36
34
import org .elasticsearch .common .settings .Setting ;
35
+ import org .elasticsearch .common .settings .Settings ;
37
36
import org .elasticsearch .common .time .DateFormatter ;
38
37
import org .elasticsearch .common .time .DateMathParser ;
39
38
import org .elasticsearch .common .util .LocaleUtils ;
40
- import org .elasticsearch .common .xcontent .XContentBuilder ;
41
39
import org .elasticsearch .common .xcontent .XContentParser ;
42
- import org .elasticsearch .common .xcontent .support .XContentMapValues ;
43
40
import org .elasticsearch .index .fielddata .IndexFieldData ;
44
41
import org .elasticsearch .index .fielddata .plain .BinaryIndexFieldData ;
45
42
import org .elasticsearch .index .query .QueryShardContext ;
55
52
import java .util .Collections ;
56
53
import java .util .HashMap ;
57
54
import java .util .HashSet ;
58
- import java .util .Iterator ;
59
55
import java .util .List ;
60
56
import java .util .Locale ;
61
57
import java .util .Map ;
69
65
import static org .elasticsearch .index .query .RangeQueryBuilder .LT_FIELD ;
70
66
71
67
/** A {@link FieldMapper} for indexing numeric and date ranges, and creating queries */
72
- public class RangeFieldMapper extends FieldMapper {
68
+ public class RangeFieldMapper extends ParametrizedFieldMapper {
73
69
public static final boolean DEFAULT_INCLUDE_UPPER = true ;
74
70
public static final boolean DEFAULT_INCLUDE_LOWER = true ;
75
71
76
72
public static class Defaults {
77
73
public static final Explicit <Boolean > COERCE = new Explicit <>(true , false );
78
- public static final FieldType FIELD_TYPE = new FieldType ();
79
- static {
80
- FIELD_TYPE .setStored (false );
81
- FIELD_TYPE .setIndexOptions (IndexOptions .DOCS );
82
- FIELD_TYPE .freeze ();
83
- }
84
74
public static final DateFormatter DATE_FORMATTER = DateFieldMapper .DEFAULT_DATE_TIME_FORMATTER ;
85
75
}
86
76
87
77
// this is private since it has a different default
88
78
static final Setting <Boolean > COERCE_SETTING =
89
79
Setting .boolSetting ("index.mapping.coerce" , true , Setting .Property .IndexScope );
90
80
91
- public static class Builder extends FieldMapper .Builder <Builder > {
92
- private Boolean coerce ;
93
- private Locale locale = Locale .ROOT ;
94
- private String pattern ;
81
+ private static RangeFieldMapper toType (FieldMapper in ) {
82
+ return (RangeFieldMapper ) in ;
83
+ }
84
+
85
+ public static class Builder extends ParametrizedFieldMapper .Builder {
86
+
87
+ private final Parameter <Boolean > index = Parameter .indexParam (m -> toType (m ).index , true );
88
+ private final Parameter <Boolean > hasDocValues = Parameter .docValuesParam (m -> toType (m ).hasDocValues , true );
89
+ private final Parameter <Boolean > store = Parameter .storeParam (m -> toType (m ).store , false );
90
+ private final Parameter <Explicit <Boolean >> coerce ;
91
+ private final Parameter <String > format
92
+ = Parameter .stringParam ("format" , false , m -> toType (m ).format , Defaults .DATE_FORMATTER .pattern ());
93
+ private final Parameter <Locale > locale = new Parameter <>("locale" , false , () -> Locale .ROOT ,
94
+ (n , c , o ) -> LocaleUtils .parse (o .toString ()), m -> toType (m ).locale );
95
+ private final Parameter <Float > boost = Parameter .boostParam ();
96
+ private final Parameter <Map <String , String >> meta = Parameter .metaParam ();
97
+
95
98
private final RangeType type ;
96
99
97
- public Builder (String name , RangeType type ) {
98
- super (name , Defaults .FIELD_TYPE );
99
- this .type = type ;
100
- builder = this ;
100
+ public Builder (String name , RangeType type , Settings settings ) {
101
+ this (name , type , COERCE_SETTING .get (settings ));
101
102
}
102
103
103
- public Builder coerce (boolean coerce ) {
104
- this .coerce = coerce ;
105
- return builder ;
104
+ public Builder (String name , RangeType type , boolean coerceByDefault ) {
105
+ super (name );
106
+ this .type = type ;
107
+ this .coerce = Parameter .explicitBoolParam ("coerce" , true , m -> toType (m ).coerce , coerceByDefault );
108
+ if (this .type != RangeType .DATE ) {
109
+ format .setShouldSerialize (() -> false );
110
+ locale .setShouldSerialize (() -> false );
111
+ }
106
112
}
107
113
108
- protected Explicit <Boolean > coerce (BuilderContext context ) {
109
- if (coerce != null ) {
110
- return new Explicit <>(coerce , true );
111
- }
112
- if (context .indexSettings () != null ) {
113
- return new Explicit <>(COERCE_SETTING .get (context .indexSettings ()), false );
114
- }
115
- return Defaults .COERCE ;
114
+ public void docValues (boolean hasDocValues ) {
115
+ this .hasDocValues .setValue (hasDocValues );
116
116
}
117
117
118
- public Builder format (String format ) {
119
- this .pattern = format ;
118
+ Builder format (String format ) {
119
+ this .format . setValue ( format ) ;
120
120
return this ;
121
121
}
122
122
123
- public void locale (Locale locale ) {
124
- this .locale = locale ;
123
+ @ Override
124
+ protected List <Parameter <?>> getParameters () {
125
+ return List .of (index , hasDocValues , store , coerce , format , locale , boost , meta );
125
126
}
126
127
127
128
protected RangeFieldType setupFieldType (BuilderContext context ) {
128
- if (pattern != null ) {
129
+ if (format . isConfigured () ) {
129
130
if (type != RangeType .DATE ) {
130
131
throw new IllegalArgumentException ("field [" + name () + "] of type [range]"
131
132
+ " should not define a dateTimeFormatter unless it is a " + RangeType .DATE + " type" );
132
133
}
133
- return new RangeFieldType (buildFullName (context ), indexed , hasDocValues ,
134
- DateFormatter .forPattern (pattern ) .withLocale (locale ) , meta );
134
+ return new RangeFieldType (buildFullName (context ), index . getValue () , hasDocValues . getValue () ,
135
+ DateFormatter .forPattern (format . getValue ()) .withLocale (locale . getValue ()) , meta . getValue () );
135
136
}
136
137
if (type == RangeType .DATE ) {
137
- return new RangeFieldType (buildFullName (context ), indexed , hasDocValues , Defaults .DATE_FORMATTER , meta );
138
+ return new RangeFieldType (buildFullName (context ), index .getValue (), hasDocValues .getValue (),
139
+ Defaults .DATE_FORMATTER , meta .getValue ());
138
140
}
139
- return new RangeFieldType (buildFullName (context ), type , indexed , hasDocValues , meta );
141
+ return new RangeFieldType (buildFullName (context ), type , index . getValue () , hasDocValues . getValue () , meta . getValue () );
140
142
}
141
143
142
144
@ Override
143
145
public RangeFieldMapper build (BuilderContext context ) {
144
- setupFieldType (context );
145
- return new RangeFieldMapper (name , fieldType , setupFieldType (context ), coerce (context ),
146
- multiFieldsBuilder .build (this , context ), copyTo );
147
- }
148
- }
149
-
150
- public static class TypeParser implements Mapper .TypeParser {
151
- final RangeType type ;
152
-
153
- public TypeParser (RangeType type ) {
154
- this .type = type ;
155
- }
156
-
157
- @ Override
158
- public Mapper .Builder <?> parse (String name , Map <String , Object > node ,
159
- ParserContext parserContext ) throws MapperParsingException {
160
- Builder builder = new Builder (name , type );
161
- TypeParsers .parseField (builder , name , node , parserContext );
162
- for (Iterator <Map .Entry <String , Object >> iterator = node .entrySet ().iterator (); iterator .hasNext ();) {
163
- Map .Entry <String , Object > entry = iterator .next ();
164
- String propName = entry .getKey ();
165
- Object propNode = entry .getValue ();
166
- if (propName .equals ("null_value" )) {
167
- throw new MapperParsingException ("Property [null_value] is not supported for [" + this .type .name
168
- + "] field types." );
169
- } else if (propName .equals ("coerce" )) {
170
- builder .coerce (XContentMapValues .nodeBooleanValue (propNode , name + ".coerce" ));
171
- iterator .remove ();
172
- } else if (propName .equals ("locale" )) {
173
- builder .locale (LocaleUtils .parse (propNode .toString ()));
174
- iterator .remove ();
175
- } else if (propName .equals ("format" )) {
176
- builder .format (propNode .toString ());
177
- iterator .remove ();
178
- } else if (TypeParsers .parseMultiField (builder ::addMultiField , name , parserContext , propName , propNode )) {
179
- iterator .remove ();
180
- }
181
- }
182
- return builder ;
146
+ RangeFieldType ft = setupFieldType (context );
147
+ ft .setBoost (boost .getValue ());
148
+ return new RangeFieldMapper (name , ft , multiFieldsBuilder .build (this , context ), copyTo .build (), type , this );
183
149
}
184
150
}
185
151
@@ -281,17 +247,37 @@ public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower
281
247
}
282
248
}
283
249
284
- private Explicit <Boolean > coerce ;
250
+ private final RangeType type ;
251
+ private final boolean index ;
252
+ private final boolean hasDocValues ;
253
+ private final boolean store ;
254
+ private final Explicit <Boolean > coerce ;
255
+ private final String format ;
256
+ private final Locale locale ;
257
+
258
+ private final boolean coerceByDefault ;
285
259
286
260
private RangeFieldMapper (
287
261
String simpleName ,
288
- FieldType fieldType ,
289
262
MappedFieldType mappedFieldType ,
290
- Explicit <Boolean > coerce ,
291
263
MultiFields multiFields ,
292
- CopyTo copyTo ) {
293
- super (simpleName , fieldType , mappedFieldType , multiFields , copyTo );
294
- this .coerce = coerce ;
264
+ CopyTo copyTo ,
265
+ RangeType type ,
266
+ Builder builder ) {
267
+ super (simpleName , mappedFieldType , multiFields , copyTo );
268
+ this .type = type ;
269
+ this .index = builder .index .getValue ();
270
+ this .hasDocValues = builder .hasDocValues .getValue ();
271
+ this .store = builder .store .getValue ();
272
+ this .coerce = builder .coerce .getValue ();
273
+ this .format = builder .format .getValue ();
274
+ this .locale = builder .locale .getValue ();
275
+ this .coerceByDefault = builder .coerce .getDefaultValue ().value ();
276
+ }
277
+
278
+ @ Override
279
+ public ParametrizedFieldMapper .Builder getMergeBuilder () {
280
+ return new Builder (simpleName (), type , coerceByDefault ).init (this );
295
281
}
296
282
297
283
@ Override
@@ -366,12 +352,9 @@ protected void parseCreateField(ParseContext context) throws IOException {
366
352
+ name () + "], expected an object but got " + parser .currentName ());
367
353
}
368
354
}
369
- boolean docValued = fieldType ().hasDocValues ();
370
- boolean indexed = fieldType ().isSearchable ();
371
- boolean stored = fieldType .stored ();
372
- context .doc ().addAll (fieldType ().rangeType .createFields (context , name (), range , indexed , docValued , stored ));
355
+ context .doc ().addAll (fieldType ().rangeType .createFields (context , name (), range , index , hasDocValues , store ));
373
356
374
- if (docValued == false && (indexed || stored )) {
357
+ if (hasDocValues == false && (index || store )) {
375
358
createFieldNamesField (context );
376
359
}
377
360
}
@@ -407,33 +390,6 @@ protected Object parseSourceValue(Object value) {
407
390
};
408
391
}
409
392
410
- @ Override
411
- protected void mergeOptions (FieldMapper other , List <String > conflicts ) {
412
- RangeFieldMapper mergeWith = (RangeFieldMapper ) other ;
413
- if (mergeWith .coerce .explicit ()) {
414
- this .coerce = mergeWith .coerce ;
415
- }
416
- }
417
-
418
- @ Override
419
- protected void doXContentBody (XContentBuilder builder , boolean includeDefaults , Params params ) throws IOException {
420
- super .doXContentBody (builder , includeDefaults , params );
421
-
422
- if (fieldType ().rangeType == RangeType .DATE
423
- && (includeDefaults || (fieldType ().dateTimeFormatter () != null
424
- && fieldType ().dateTimeFormatter ().pattern ().equals (DateFieldMapper .DEFAULT_DATE_TIME_FORMATTER .pattern ()) == false ))) {
425
- builder .field ("format" , fieldType ().dateTimeFormatter ().pattern ());
426
- }
427
- if (fieldType ().rangeType == RangeType .DATE
428
- && (includeDefaults || (fieldType ().dateTimeFormatter () != null
429
- && fieldType ().dateTimeFormatter ().locale () != Locale .ROOT ))) {
430
- builder .field ("locale" , fieldType ().dateTimeFormatter ().locale ());
431
- }
432
- if (includeDefaults || coerce .explicit ()) {
433
- builder .field ("coerce" , coerce .value ());
434
- }
435
- }
436
-
437
393
private static Range parseIpRangeFromCidr (final XContentParser parser ) throws IOException {
438
394
final Tuple <InetAddress , Integer > cidr = InetAddresses .parseCidr (parser .text ());
439
395
// create the lower value by zeroing out the host portion, upper value by filling it with all ones.
@@ -456,8 +412,8 @@ public static class Range {
456
412
RangeType type ;
457
413
Object from ;
458
414
Object to ;
459
- private boolean includeFrom ;
460
- private boolean includeTo ;
415
+ private final boolean includeFrom ;
416
+ private final boolean includeTo ;
461
417
462
418
public Range (RangeType type , Object from , Object to , boolean includeFrom , boolean includeTo ) {
463
419
this .type = type ;
0 commit comments