20
20
import org .elasticsearch .search .aggregations .metrics .GeoBounds ;
21
21
import org .elasticsearch .search .aggregations .metrics .GeoCentroid ;
22
22
import org .elasticsearch .search .aggregations .metrics .NumericMetricsAggregation .SingleValue ;
23
+ import org .elasticsearch .search .aggregations .metrics .Percentile ;
24
+ import org .elasticsearch .search .aggregations .metrics .Percentiles ;
23
25
import org .elasticsearch .search .aggregations .metrics .ScriptedMetric ;
24
26
import org .elasticsearch .xpack .core .transform .TransformField ;
25
27
import org .elasticsearch .xpack .core .transform .transforms .TransformIndexerStats ;
26
28
import org .elasticsearch .xpack .core .transform .transforms .pivot .GroupConfig ;
27
29
import org .elasticsearch .xpack .transform .transforms .IDGenerator ;
30
+ import org .elasticsearch .xpack .transform .utils .OutputFieldNameConverter ;
28
31
29
32
import java .util .Arrays ;
30
33
import java .util .Collection ;
@@ -46,6 +49,7 @@ public final class AggregationResultUtils {
46
49
tempMap .put (ScriptedMetric .class .getName (), new ScriptedMetricAggExtractor ());
47
50
tempMap .put (GeoCentroid .class .getName (), new GeoCentroidAggExtractor ());
48
51
tempMap .put (GeoBounds .class .getName (), new GeoBoundsAggExtractor ());
52
+ tempMap .put (Percentiles .class .getName (), new PercentilesAggExtractor ());
49
53
TYPE_VALUE_EXTRACTOR_MAP = Collections .unmodifiableMap (tempMap );
50
54
}
51
55
@@ -59,12 +63,14 @@ public final class AggregationResultUtils {
59
63
* @param stats stats collector
60
64
* @return a map containing the results of the aggregation in a consumable way
61
65
*/
62
- public static Stream <Map <String , Object >> extractCompositeAggregationResults (CompositeAggregation agg ,
63
- GroupConfig groups ,
64
- Collection <AggregationBuilder > aggregationBuilders ,
65
- Collection <PipelineAggregationBuilder > pipelineAggs ,
66
- Map <String , String > fieldTypeMap ,
67
- TransformIndexerStats stats ) {
66
+ public static Stream <Map <String , Object >> extractCompositeAggregationResults (
67
+ CompositeAggregation agg ,
68
+ GroupConfig groups ,
69
+ Collection <AggregationBuilder > aggregationBuilders ,
70
+ Collection <PipelineAggregationBuilder > pipelineAggs ,
71
+ Map <String , String > fieldTypeMap ,
72
+ TransformIndexerStats stats
73
+ ) {
68
74
return agg .getBuckets ().stream ().map (bucket -> {
69
75
stats .incrementNumDocuments (bucket .getDocCount ());
70
76
Map <String , Object > document = new HashMap <>();
@@ -82,7 +88,7 @@ public static Stream<Map<String, Object>> extractCompositeAggregationResults(Com
82
88
List <String > aggNames = aggregationBuilders .stream ().map (AggregationBuilder ::getName ).collect (Collectors .toList ());
83
89
aggNames .addAll (pipelineAggs .stream ().map (PipelineAggregationBuilder ::getName ).collect (Collectors .toList ()));
84
90
85
- for (String aggName : aggNames ) {
91
+ for (String aggName : aggNames ) {
86
92
Aggregation aggResult = bucket .getAggregations ().get (aggName );
87
93
// This indicates not that the value contained in the `aggResult` is null, but that the `aggResult` is not
88
94
// present at all in the `bucket.getAggregations`. This could occur in the case of a `bucket_selector` agg, which
@@ -109,16 +115,19 @@ static AggValueExtractor getExtractor(Aggregation aggregation) {
109
115
return TYPE_VALUE_EXTRACTOR_MAP .get (GeoCentroid .class .getName ());
110
116
} else if (aggregation instanceof GeoBounds ) {
111
117
return TYPE_VALUE_EXTRACTOR_MAP .get (GeoBounds .class .getName ());
118
+ } else if (aggregation instanceof Percentiles ) {
119
+ return TYPE_VALUE_EXTRACTOR_MAP .get (Percentiles .class .getName ());
112
120
} else {
113
121
// Execution should never reach this point!
114
122
// Creating transforms with unsupported aggregations shall not be possible
115
- throw new AggregationExtractionException ("unsupported aggregation [{}] with name [{}]" ,
123
+ throw new AggregationExtractionException (
124
+ "unsupported aggregation [{}] with name [{}]" ,
116
125
aggregation .getType (),
117
- aggregation .getName ());
126
+ aggregation .getName ()
127
+ );
118
128
}
119
129
}
120
130
121
-
122
131
@ SuppressWarnings ("unchecked" )
123
132
static void updateDocument (Map <String , Object > document , String fieldName , Object value ) {
124
133
String [] fieldTokens = fieldName .split ("\\ ." );
@@ -132,23 +141,23 @@ static void updateDocument(Map<String, Object> document, String fieldName, Objec
132
141
if (i == fieldTokens .length - 1 ) {
133
142
if (internalMap .containsKey (token )) {
134
143
if (internalMap .get (token ) instanceof Map ) {
135
- throw new AggregationExtractionException ("mixed object types of nested and non-nested fields [{}]" ,
136
- fieldName );
144
+ throw new AggregationExtractionException ("mixed object types of nested and non-nested fields [{}]" , fieldName );
137
145
} else {
138
- throw new AggregationExtractionException ("duplicate key value pairs key [{}] old value [{}] duplicate value [{}]" ,
146
+ throw new AggregationExtractionException (
147
+ "duplicate key value pairs key [{}] old value [{}] duplicate value [{}]" ,
139
148
fieldName ,
140
149
internalMap .get (token ),
141
- value );
150
+ value
151
+ );
142
152
}
143
153
}
144
154
internalMap .put (token , value );
145
155
} else {
146
156
if (internalMap .containsKey (token )) {
147
157
if (internalMap .get (token ) instanceof Map ) {
148
- internalMap = (Map <String , Object >)internalMap .get (token );
158
+ internalMap = (Map <String , Object >) internalMap .get (token );
149
159
} else {
150
- throw new AggregationExtractionException ("mixed object types of nested and non-nested fields [{}]" ,
151
- fieldName );
160
+ throw new AggregationExtractionException ("mixed object types of nested and non-nested fields [{}]" , fieldName );
152
161
}
153
162
} else {
154
163
Map <String , Object > newMap = new HashMap <>();
@@ -172,34 +181,48 @@ interface AggValueExtractor {
172
181
static class SingleValueAggExtractor implements AggValueExtractor {
173
182
@ Override
174
183
public Object value (Aggregation agg , String fieldType ) {
175
- SingleValue aggregation = (SingleValue )agg ;
184
+ SingleValue aggregation = (SingleValue ) agg ;
176
185
// If the double is invalid, this indicates sparse data
177
186
if (Numbers .isValidDouble (aggregation .value ()) == false ) {
178
187
return null ;
179
188
}
180
189
// If the type is numeric or if the formatted string is the same as simply making the value a string,
181
- // gather the `value` type, otherwise utilize `getValueAsString` so we don't lose formatted outputs.
182
- if (isNumericType (fieldType ) ||
183
- aggregation .getValueAsString ().equals (String .valueOf (aggregation .value ()))){
190
+ // gather the `value` type, otherwise utilize `getValueAsString` so we don't lose formatted outputs.
191
+ if (isNumericType (fieldType ) || aggregation .getValueAsString ().equals (String .valueOf (aggregation .value ()))) {
184
192
return aggregation .value ();
185
193
} else {
186
194
return aggregation .getValueAsString ();
187
195
}
188
196
}
189
197
}
190
198
199
+ static class PercentilesAggExtractor implements AggValueExtractor {
200
+ @ Override
201
+ public Object value (Aggregation agg , String fieldType ) {
202
+ Percentiles aggregation = (Percentiles ) agg ;
203
+
204
+ HashMap <String , Double > percentiles = new HashMap <>();
205
+
206
+ for (Percentile p : aggregation ) {
207
+ percentiles .put (OutputFieldNameConverter .fromDouble (p .getPercent ()), p .getValue ());
208
+ }
209
+
210
+ return percentiles ;
211
+ }
212
+ }
213
+
191
214
static class ScriptedMetricAggExtractor implements AggValueExtractor {
192
215
@ Override
193
216
public Object value (Aggregation agg , String fieldType ) {
194
- ScriptedMetric aggregation = (ScriptedMetric )agg ;
217
+ ScriptedMetric aggregation = (ScriptedMetric ) agg ;
195
218
return aggregation .aggregation ();
196
219
}
197
220
}
198
221
199
222
static class GeoCentroidAggExtractor implements AggValueExtractor {
200
223
@ Override
201
224
public Object value (Aggregation agg , String fieldType ) {
202
- GeoCentroid aggregation = (GeoCentroid )agg ;
225
+ GeoCentroid aggregation = (GeoCentroid ) agg ;
203
226
// if the account is `0` iff there is no contained centroid
204
227
return aggregation .count () > 0 ? aggregation .centroid ().toString () : null ;
205
228
}
@@ -208,38 +231,49 @@ public Object value(Aggregation agg, String fieldType) {
208
231
static class GeoBoundsAggExtractor implements AggValueExtractor {
209
232
@ Override
210
233
public Object value (Aggregation agg , String fieldType ) {
211
- GeoBounds aggregation = (GeoBounds )agg ;
234
+ GeoBounds aggregation = (GeoBounds ) agg ;
212
235
if (aggregation .bottomRight () == null || aggregation .topLeft () == null ) {
213
236
return null ;
214
237
}
215
238
final Map <String , Object > geoShape = new HashMap <>();
216
239
// If the two geo_points are equal, it is a point
217
240
if (aggregation .topLeft ().equals (aggregation .bottomRight ())) {
218
241
geoShape .put (ShapeParser .FIELD_TYPE .getPreferredName (), PointBuilder .TYPE .shapeName ());
219
- geoShape .put (ShapeParser .FIELD_COORDINATES .getPreferredName (),
220
- Arrays .asList (aggregation .topLeft ().getLon (), aggregation .bottomRight ().getLat ()));
221
- // If only the lat or the lon of the two geo_points are equal, than we know it should be a line
242
+ geoShape .put (
243
+ ShapeParser .FIELD_COORDINATES .getPreferredName (),
244
+ Arrays .asList (aggregation .topLeft ().getLon (), aggregation .bottomRight ().getLat ())
245
+ );
246
+ // If only the lat or the lon of the two geo_points are equal, than we know it should be a line
222
247
} else if (Double .compare (aggregation .topLeft ().getLat (), aggregation .bottomRight ().getLat ()) == 0
223
248
|| Double .compare (aggregation .topLeft ().getLon (), aggregation .bottomRight ().getLon ()) == 0 ) {
224
- geoShape .put (ShapeParser .FIELD_TYPE .getPreferredName (), LineStringBuilder .TYPE .shapeName ());
225
- geoShape .put (ShapeParser .FIELD_COORDINATES .getPreferredName (),
226
- Arrays .asList (
227
- new Double []{aggregation .topLeft ().getLon (), aggregation .topLeft ().getLat ()},
228
- new Double []{aggregation .bottomRight ().getLon (), aggregation .bottomRight ().getLat ()}));
229
- } else {
230
- // neither points are equal, we have a polygon that is a square
231
- geoShape .put (ShapeParser .FIELD_TYPE .getPreferredName (), PolygonBuilder .TYPE .shapeName ());
232
- final GeoPoint tl = aggregation .topLeft ();
233
- final GeoPoint br = aggregation .bottomRight ();
234
- geoShape .put (ShapeParser .FIELD_COORDINATES .getPreferredName (),
235
- Collections .singletonList (Arrays .asList (
236
- new Double []{tl .getLon (), tl .getLat ()},
237
- new Double []{br .getLon (), tl .getLat ()},
238
- new Double []{br .getLon (), br .getLat ()},
239
- new Double []{tl .getLon (), br .getLat ()},
240
- new Double []{tl .getLon (), tl .getLat ()})));
241
- }
249
+ geoShape .put (ShapeParser .FIELD_TYPE .getPreferredName (), LineStringBuilder .TYPE .shapeName ());
250
+ geoShape .put (
251
+ ShapeParser .FIELD_COORDINATES .getPreferredName (),
252
+ Arrays .asList (
253
+ new Double [] { aggregation .topLeft ().getLon (), aggregation .topLeft ().getLat () },
254
+ new Double [] { aggregation .bottomRight ().getLon (), aggregation .bottomRight ().getLat () }
255
+ )
256
+ );
257
+ } else {
258
+ // neither points are equal, we have a polygon that is a square
259
+ geoShape .put (ShapeParser .FIELD_TYPE .getPreferredName (), PolygonBuilder .TYPE .shapeName ());
260
+ final GeoPoint tl = aggregation .topLeft ();
261
+ final GeoPoint br = aggregation .bottomRight ();
262
+ geoShape .put (
263
+ ShapeParser .FIELD_COORDINATES .getPreferredName (),
264
+ Collections .singletonList (
265
+ Arrays .asList (
266
+ new Double [] { tl .getLon (), tl .getLat () },
267
+ new Double [] { br .getLon (), tl .getLat () },
268
+ new Double [] { br .getLon (), br .getLat () },
269
+ new Double [] { tl .getLon (), br .getLat () },
270
+ new Double [] { tl .getLon (), tl .getLat () }
271
+ )
272
+ )
273
+ );
274
+ }
242
275
return geoShape ;
243
276
}
244
277
}
278
+
245
279
}
0 commit comments