40
40
*
41
41
* A limitation of this class is that all the ValuesSource's being refereenced must be of the same type.
42
42
*/
43
- public abstract class MultiValuesSourceAggregationBuilder <VS extends ValuesSource , AB extends MultiValuesSourceAggregationBuilder <VS , AB >>
43
+ public abstract class MultiValuesSourceAggregationBuilder <AB extends MultiValuesSourceAggregationBuilder <AB >>
44
44
extends AbstractAggregationBuilder <AB > {
45
45
46
46
47
- public abstract static class LeafOnly <VS extends ValuesSource , AB extends MultiValuesSourceAggregationBuilder <VS , AB >>
48
- extends MultiValuesSourceAggregationBuilder <VS , AB > {
47
+ public abstract static class LeafOnly <AB extends MultiValuesSourceAggregationBuilder <AB >>
48
+ extends MultiValuesSourceAggregationBuilder <AB > {
49
49
50
- protected LeafOnly (String name , ValueType targetValueType ) {
51
- super (name , targetValueType );
50
+ protected LeafOnly (String name ) {
51
+ super (name );
52
52
}
53
53
54
- protected LeafOnly (LeafOnly <VS , AB > clone , Builder factoriesBuilder , Map <String , Object > metaData ) {
54
+ protected LeafOnly (LeafOnly <AB > clone , Builder factoriesBuilder , Map <String , Object > metaData ) {
55
55
super (clone , factoriesBuilder , metaData );
56
56
if (factoriesBuilder .count () > 0 ) {
57
57
throw new AggregationInitializationException ("Aggregator [" + name + "] of type ["
@@ -62,8 +62,8 @@ protected LeafOnly(LeafOnly<VS, AB> clone, Builder factoriesBuilder, Map<String,
62
62
/**
63
63
* Read from a stream that does not serialize its targetValueType. This should be used by most subclasses.
64
64
*/
65
- protected LeafOnly (StreamInput in , ValueType targetValueType ) throws IOException {
66
- super (in , targetValueType );
65
+ protected LeafOnly (StreamInput in ) throws IOException {
66
+ super (in );
67
67
}
68
68
69
69
@ Override
@@ -76,30 +76,28 @@ public AB subAggregations(Builder subFactories) {
76
76
77
77
78
78
private Map <String , MultiValuesSourceFieldConfig > fields = new HashMap <>();
79
- private final ValueType targetValueType ;
80
- private ValueType valueType = null ;
79
+ private ValueType userValueTypeHint = null ;
81
80
private String format = null ;
82
81
83
- protected MultiValuesSourceAggregationBuilder (String name , ValueType targetValueType ) {
82
+ protected MultiValuesSourceAggregationBuilder (String name ) {
84
83
super (name );
85
- this .targetValueType = targetValueType ;
86
84
}
87
85
88
- protected MultiValuesSourceAggregationBuilder (MultiValuesSourceAggregationBuilder <VS , AB > clone ,
86
+ protected MultiValuesSourceAggregationBuilder (MultiValuesSourceAggregationBuilder <AB > clone ,
89
87
Builder factoriesBuilder , Map <String , Object > metaData ) {
90
88
super (clone , factoriesBuilder , metaData );
91
89
92
90
this .fields = new HashMap <>(clone .fields );
93
- this .targetValueType = clone .targetValueType ;
94
- this .valueType = clone .valueType ;
91
+ this .userValueTypeHint = clone .userValueTypeHint ;
95
92
this .format = clone .format ;
96
93
}
97
94
98
- protected MultiValuesSourceAggregationBuilder (StreamInput in , ValueType targetValueType )
95
+ /**
96
+ * Read from a stream.
97
+ */
98
+ protected MultiValuesSourceAggregationBuilder (StreamInput in )
99
99
throws IOException {
100
100
super (in );
101
- assert false == serializeTargetValueType () : "Wrong read constructor called for subclass that provides its targetValueType" ;
102
- this .targetValueType = targetValueType ;
103
101
read (in );
104
102
}
105
103
@@ -109,17 +107,14 @@ protected MultiValuesSourceAggregationBuilder(StreamInput in, ValueType targetVa
109
107
@ SuppressWarnings ("unchecked" )
110
108
private void read (StreamInput in ) throws IOException {
111
109
fields = in .readMap (StreamInput ::readString , MultiValuesSourceFieldConfig ::new );
112
- valueType = in .readOptionalWriteable (ValueType ::readFromStream );
110
+ userValueTypeHint = in .readOptionalWriteable (ValueType ::readFromStream );
113
111
format = in .readOptionalString ();
114
112
}
115
113
116
114
@ Override
117
115
protected final void doWriteTo (StreamOutput out ) throws IOException {
118
- if (serializeTargetValueType ()) {
119
- out .writeOptionalWriteable (targetValueType );
120
- }
121
116
out .writeMap (fields , StreamOutput ::writeString , (o , value ) -> value .writeTo (o ));
122
- out .writeOptionalWriteable (valueType );
117
+ out .writeOptionalWriteable (userValueTypeHint );
123
118
out .writeOptionalString (format );
124
119
innerWriteTo (out );
125
120
}
@@ -142,11 +137,11 @@ protected AB field(String propertyName, MultiValuesSourceFieldConfig config) {
142
137
* Sets the {@link ValueType} for the value produced by this aggregation
143
138
*/
144
139
@ SuppressWarnings ("unchecked" )
145
- public AB valueType (ValueType valueType ) {
140
+ public AB userValueTypeHint (ValueType valueType ) {
146
141
if (valueType == null ) {
147
- throw new IllegalArgumentException ("[valueType ] must not be null: [" + name + "]" );
142
+ throw new IllegalArgumentException ("[userValueTypeHint ] must not be null: [" + name + "]" );
148
143
}
149
- this .valueType = valueType ;
144
+ this .userValueTypeHint = valueType ;
150
145
return (AB ) this ;
151
146
}
152
147
@@ -162,25 +157,34 @@ public AB format(String format) {
162
157
return (AB ) this ;
163
158
}
164
159
165
- @ Override
166
- protected final MultiValuesSourceAggregatorFactory <VS > doBuild (QueryShardContext queryShardContext , AggregatorFactory parent ,
167
- Builder subFactoriesBuilder ) throws IOException {
168
- ValueType finalValueType = this .valueType != null ? this .valueType : targetValueType ;
160
+ /**
161
+ * Aggregations should use this method to define a {@link ValuesSourceType} of last resort. This will only be used when the resolver
162
+ * can't find a field and the user hasn't provided a value type hint.
163
+ *
164
+ * @return The CoreValuesSourceType we expect this script to yield.
165
+ */
166
+ protected abstract ValuesSourceType defaultValueSourceType ();
169
167
168
+ @ Override
169
+ protected final MultiValuesSourceAggregatorFactory doBuild (QueryShardContext queryShardContext , AggregatorFactory parent ,
170
+ Builder subFactoriesBuilder ) throws IOException {
170
171
Map <String , ValuesSourceConfig > configs = new HashMap <>(fields .size ());
171
172
fields .forEach ((key , value ) -> {
172
- ValuesSourceConfig config = ValuesSourceConfig .resolve (queryShardContext , finalValueType ,
173
- value .getFieldName (), value .getScript (), value .getMissing (), value .getTimeZone (), format , getType ());
173
+ ValuesSourceConfig config = ValuesSourceConfig .resolve (queryShardContext , userValueTypeHint ,
174
+ value .getFieldName (), value .getScript (), value .getMissing (), value .getTimeZone (), format , defaultValueSourceType (),
175
+ getType ());
174
176
configs .put (key , config );
175
177
});
176
- DocValueFormat docValueFormat = resolveFormat (format , finalValueType );
178
+ DocValueFormat docValueFormat = resolveFormat (format , userValueTypeHint , defaultValueSourceType () );
177
179
return innerBuild (queryShardContext , configs , docValueFormat , parent , subFactoriesBuilder );
178
180
}
179
181
180
182
181
- private static DocValueFormat resolveFormat (@ Nullable String format , @ Nullable ValueType valueType ) {
183
+ private static DocValueFormat resolveFormat (@ Nullable String format , @ Nullable ValueType valueType ,
184
+ ValuesSourceType defaultValuesSourceType ) {
182
185
if (valueType == null ) {
183
- return DocValueFormat .RAW ; // we can't figure it out
186
+ // If the user didn't send a hint, all we can do is fall back to the default
187
+ return defaultValuesSourceType .getFormatter (format , null );
184
188
}
185
189
DocValueFormat valueFormat = valueType .defaultFormat ;
186
190
if (valueFormat instanceof DocValueFormat .Decimal && format != null ) {
@@ -189,19 +193,11 @@ private static DocValueFormat resolveFormat(@Nullable String format, @Nullable V
189
193
return valueFormat ;
190
194
}
191
195
192
- protected abstract MultiValuesSourceAggregatorFactory <VS > innerBuild (QueryShardContext queryShardContext ,
193
- Map <String , ValuesSourceConfig > configs ,
194
- DocValueFormat format , AggregatorFactory parent ,
195
- Builder subFactoriesBuilder ) throws IOException ;
196
-
196
+ protected abstract MultiValuesSourceAggregatorFactory innerBuild (QueryShardContext queryShardContext ,
197
+ Map <String , ValuesSourceConfig > configs ,
198
+ DocValueFormat format , AggregatorFactory parent ,
199
+ Builder subFactoriesBuilder ) throws IOException ;
197
200
198
- /**
199
- * Should this builder serialize its targetValueType? Defaults to false. All subclasses that override this to true
200
- * should use the three argument read constructor rather than the four argument version.
201
- */
202
- protected boolean serializeTargetValueType () {
203
- return false ;
204
- }
205
201
206
202
@ Override
207
203
public final XContentBuilder internalXContent (XContentBuilder builder , Params params ) throws IOException {
@@ -214,8 +210,8 @@ public final XContentBuilder internalXContent(XContentBuilder builder, Params pa
214
210
if (format != null ) {
215
211
builder .field (CommonFields .FORMAT .getPreferredName (), format );
216
212
}
217
- if (valueType != null ) {
218
- builder .field (CommonFields .VALUE_TYPE .getPreferredName (), valueType .getPreferredName ());
213
+ if (userValueTypeHint != null ) {
214
+ builder .field (CommonFields .VALUE_TYPE .getPreferredName (), userValueTypeHint .getPreferredName ());
219
215
}
220
216
doXContentBody (builder , params );
221
217
builder .endObject ();
@@ -226,7 +222,7 @@ public final XContentBuilder internalXContent(XContentBuilder builder, Params pa
226
222
227
223
@ Override
228
224
public int hashCode () {
229
- return Objects .hash (super .hashCode (), fields , format , targetValueType , valueType );
225
+ return Objects .hash (super .hashCode (), fields , format , userValueTypeHint );
230
226
}
231
227
232
228
@@ -239,6 +235,6 @@ public boolean equals(Object obj) {
239
235
MultiValuesSourceAggregationBuilder other = (MultiValuesSourceAggregationBuilder ) obj ;
240
236
return Objects .equals (this .fields , other .fields )
241
237
&& Objects .equals (this .format , other .format )
242
- && Objects .equals (this .valueType , other .valueType );
238
+ && Objects .equals (this .userValueTypeHint , other .userValueTypeHint );
243
239
}
244
240
}
0 commit comments