17
17
import org .hibernate .search .engine .backend .types .converter .spi .ProjectionConverter ;
18
18
import org .hibernate .search .engine .search .aggregation .spi .FieldMetricAggregationBuilder ;
19
19
import org .hibernate .search .engine .search .common .ValueModel ;
20
- import org .hibernate .search .util .common .AssertionFailure ;
21
20
22
21
import com .google .gson .JsonElement ;
23
22
import com .google .gson .JsonObject ;
@@ -64,15 +63,13 @@ public static <F> ElasticsearchMetricFieldAggregation.Factory<F> avg(Elasticsear
64
63
}
65
64
66
65
private final String absoluteFieldPath ;
67
- private final ProjectionConverter <F , ? extends K > fromFieldValueConverter ;
68
- private final ElasticsearchFieldCodec <F > codec ;
66
+ private final AggregationExtractorBuilder <K > metricFieldExtractorCreator ;
69
67
private final JsonAccessor <JsonObject > operation ;
70
68
71
69
private ElasticsearchMetricFieldAggregation (Builder <F , K > builder ) {
72
70
super ( builder );
73
71
this .absoluteFieldPath = builder .field .absolutePath ();
74
- this .fromFieldValueConverter = builder .fromFieldValueConverter ;
75
- this .codec = builder .codec ;
72
+ this .metricFieldExtractorCreator = builder .metricFieldExtractorCreator ;
76
73
this .operation = builder .operation ;
77
74
}
78
75
@@ -88,7 +85,7 @@ protected final JsonObject doRequest(AggregationRequestContext context) {
88
85
89
86
@ Override
90
87
protected Extractor <K > extractor (AggregationRequestContext context ) {
91
- return new MetricFieldExtractor ( nestedPathHierarchy , filter );
88
+ return metricFieldExtractorCreator . extractor ( filter );
92
89
}
93
90
94
91
private static class Factory <F >
@@ -124,72 +121,155 @@ private TypeSelector(ElasticsearchFieldCodec<F> codec,
124
121
this .operation = operation ;
125
122
}
126
123
124
+ @ SuppressWarnings ("unchecked" )
127
125
@ Override
128
126
public <T > Builder <F , T > type (Class <T > expectedType , ValueModel valueModel ) {
129
- ProjectionConverter <F , ? extends T > projectionConverter = null ;
130
- if ( useProjectionConverter ( expectedType , valueModel ) ) {
131
- projectionConverter = field .type ().projectionConverter ( valueModel )
132
- .withConvertedType ( expectedType , field );
133
- }
134
- return new Builder <>( codec , scope , field ,
135
- projectionConverter ,
136
- operation
137
- );
138
- }
127
+ AggregationExtractorBuilder <T > metricFieldExtractorCreator ;
139
128
140
- private <T > boolean useProjectionConverter (Class <T > expectedType , ValueModel valueModel ) {
141
- if ( !Double .class .isAssignableFrom ( expectedType ) ) {
142
- if ( ValueModel .RAW .equals ( valueModel ) ) {
143
- throw new AssertionFailure (
144
- "Raw projection converter is not supported with metric aggregations at the moment" );
129
+ if ( ValueModel .RAW .equals ( valueModel ) ) {
130
+ if ( Double .class .isAssignableFrom ( expectedType ) ) {
131
+ metricFieldExtractorCreator = (AggregationExtractorBuilder <
132
+ T >) new DoubleMetricFieldExtractor .Builder ( field .nestedPathHierarchy () );
133
+ }
134
+ else {
135
+ var projectionConverter = (ProjectionConverter <JsonElement , ? extends T >) field .type ()
136
+ .rawProjectionConverter ().withConvertedType ( expectedType , field );
137
+ metricFieldExtractorCreator = (AggregationExtractorBuilder <T >) new RawMetricFieldExtractor .Builder <>(
138
+ field .nestedPathHierarchy (),
139
+ projectionConverter );
145
140
}
146
- return true ;
147
141
}
148
-
149
- // expectedType == Double.class
150
- if ( ValueModel .RAW .equals ( valueModel ) ) {
151
- return false ;
142
+ else {
143
+ var projectionConverter = field .type ()
144
+ .projectionConverter ( valueModel ).withConvertedType ( expectedType , field );
145
+ metricFieldExtractorCreator =
146
+ new MetricFieldExtractor .Builder <>( field .nestedPathHierarchy (), projectionConverter , codec );
152
147
}
153
- return field .type ().projectionConverter ( valueModel ).valueType ().isAssignableFrom ( Double .class );
148
+
149
+ return new Builder <>( scope , field , metricFieldExtractorCreator , operation );
154
150
}
155
151
}
156
152
157
- private class MetricFieldExtractor extends AbstractExtractor <K > {
158
- protected MetricFieldExtractor (List <String > nestedPathHierarchy , ElasticsearchSearchPredicate filter ) {
153
+ private static class MetricFieldExtractor <F , K > extends AbstractExtractor <K > {
154
+
155
+ private final ProjectionConverter <F , ? extends K > fromFieldValueConverter ;
156
+ private final ElasticsearchFieldCodec <F > codec ;
157
+
158
+ protected MetricFieldExtractor (List <String > nestedPathHierarchy , ElasticsearchSearchPredicate filter ,
159
+ ProjectionConverter <F , ? extends K > fromFieldValueConverter , ElasticsearchFieldCodec <F > codec ) {
159
160
super ( nestedPathHierarchy , filter );
161
+ this .fromFieldValueConverter = fromFieldValueConverter ;
162
+ this .codec = codec ;
160
163
}
161
164
162
165
@ Override
163
- @ SuppressWarnings ("unchecked" )
164
166
protected K doExtract (JsonObject aggregationResult , AggregationExtractContext context ) {
165
167
FromDocumentValueConvertContext convertContext = context .fromDocumentValueConvertContext ();
166
168
Optional <Double > value = VALUE_ACCESSOR .get ( aggregationResult );
167
169
JsonElement valueAsString = aggregationResult .get ( "value_as_string" );
168
170
169
- if ( fromFieldValueConverter == null ) {
170
- Double decode = value .orElse ( null );
171
- return (K ) decode ;
172
- }
171
+
173
172
return fromFieldValueConverter .fromDocumentValue (
174
173
codec .decodeAggregationValue ( value , valueAsString ),
175
174
convertContext
176
175
);
177
176
}
177
+
178
+ private static class Builder <F , K > extends AggregationExtractorBuilder <K > {
179
+ private final ProjectionConverter <F , ? extends K > fromFieldValueConverter ;
180
+ private final ElasticsearchFieldCodec <F > codec ;
181
+
182
+ private Builder (List <String > nestedPathHierarchy , ProjectionConverter <F , ? extends K > fromFieldValueConverter ,
183
+ ElasticsearchFieldCodec <F > codec ) {
184
+ super ( nestedPathHierarchy );
185
+ this .fromFieldValueConverter = fromFieldValueConverter ;
186
+ this .codec = codec ;
187
+ }
188
+
189
+ @ Override
190
+ AbstractExtractor <K > extractor (ElasticsearchSearchPredicate filter ) {
191
+ return new MetricFieldExtractor <>( nestedPathHierarchy , filter , fromFieldValueConverter , codec );
192
+ }
193
+ }
194
+ }
195
+
196
+ private static class DoubleMetricFieldExtractor extends AbstractExtractor <Double > {
197
+ protected DoubleMetricFieldExtractor (List <String > nestedPathHierarchy , ElasticsearchSearchPredicate filter ) {
198
+ super ( nestedPathHierarchy , filter );
199
+ }
200
+
201
+ @ Override
202
+ protected Double doExtract (JsonObject aggregationResult , AggregationExtractContext context ) {
203
+ Optional <Double > value = VALUE_ACCESSOR .get ( aggregationResult );
204
+ return value .orElse ( null );
205
+ }
206
+
207
+ private static class Builder extends AggregationExtractorBuilder <Double > {
208
+
209
+ private Builder (List <String > nestedPathHierarchy ) {
210
+ super ( nestedPathHierarchy );
211
+ }
212
+
213
+ @ Override
214
+ AbstractExtractor <Double > extractor (ElasticsearchSearchPredicate filter ) {
215
+ return new DoubleMetricFieldExtractor ( nestedPathHierarchy , filter );
216
+ }
217
+ }
218
+ }
219
+
220
+ private static class RawMetricFieldExtractor <K > extends AbstractExtractor <K > {
221
+
222
+ private final ProjectionConverter <JsonElement , K > projectionConverter ;
223
+
224
+ protected RawMetricFieldExtractor (List <String > nestedPathHierarchy , ElasticsearchSearchPredicate filter ,
225
+ ProjectionConverter <JsonElement , K > projectionConverter ) {
226
+ super ( nestedPathHierarchy , filter );
227
+ this .projectionConverter = projectionConverter ;
228
+ }
229
+
230
+ @ Override
231
+ protected K doExtract (JsonObject aggregationResult , AggregationExtractContext context ) {
232
+ FromDocumentValueConvertContext convertContext = context .fromDocumentValueConvertContext ();
233
+ return projectionConverter .fromDocumentValue ( aggregationResult , convertContext );
234
+ }
235
+
236
+ private static class Builder <K > extends AggregationExtractorBuilder <K > {
237
+ private final ProjectionConverter <JsonElement , K > projectionConverter ;
238
+
239
+ private Builder (List <String > nestedPathHierarchy , ProjectionConverter <JsonElement , K > projectionConverter ) {
240
+ super ( nestedPathHierarchy );
241
+ this .projectionConverter = projectionConverter ;
242
+ }
243
+
244
+ @ Override
245
+ AbstractExtractor <K > extractor (ElasticsearchSearchPredicate filter ) {
246
+ return new RawMetricFieldExtractor <>( nestedPathHierarchy , filter , projectionConverter );
247
+ }
248
+ }
249
+ }
250
+
251
+ private abstract static class AggregationExtractorBuilder <K > {
252
+ protected final List <String > nestedPathHierarchy ;
253
+
254
+ protected AggregationExtractorBuilder (List <String > nestedPathHierarchy ) {
255
+ this .nestedPathHierarchy = nestedPathHierarchy ;
256
+ }
257
+
258
+ abstract AbstractExtractor <K > extractor (ElasticsearchSearchPredicate filter );
178
259
}
179
260
180
261
private static class Builder <F , K > extends AbstractBuilder <K >
181
262
implements FieldMetricAggregationBuilder <K > {
182
263
183
- private final ElasticsearchFieldCodec <F > codec ;
184
- private final ProjectionConverter <F , ? extends K > fromFieldValueConverter ;
264
+ private final AggregationExtractorBuilder <K > metricFieldExtractorCreator ;
185
265
private final JsonAccessor <JsonObject > operation ;
186
266
187
- private Builder (ElasticsearchFieldCodec < F > codec , ElasticsearchSearchIndexScope <?> scope ,
267
+ private Builder (ElasticsearchSearchIndexScope <?> scope ,
188
268
ElasticsearchSearchIndexValueFieldContext <F > field ,
189
- ProjectionConverter <F , ? extends K > fromFieldValueConverter , JsonAccessor <JsonObject > operation ) {
269
+ AggregationExtractorBuilder <K > metricFieldExtractorCreator ,
270
+ JsonAccessor <JsonObject > operation ) {
190
271
super ( scope , field );
191
- this .codec = codec ;
192
- this .fromFieldValueConverter = fromFieldValueConverter ;
272
+ this .metricFieldExtractorCreator = metricFieldExtractorCreator ;
193
273
this .operation = operation ;
194
274
}
195
275
0 commit comments