34
34
import org .elasticsearch .common .settings .Settings ;
35
35
import org .elasticsearch .index .fielddata .IndexFieldData ;
36
36
import org .elasticsearch .index .fielddata .IndexNumericFieldData ;
37
- import org .elasticsearch .index .mapper .GeoPointFieldMapper .GeoPointFieldType ;
38
37
import org .elasticsearch .index .mapper .DateFieldMapper ;
38
+ import org .elasticsearch .index .mapper .GeoPointFieldMapper .GeoPointFieldType ;
39
39
import org .elasticsearch .index .mapper .MappedFieldType ;
40
40
import org .elasticsearch .index .mapper .MapperService ;
41
+ import org .elasticsearch .script .BucketAggregationScript ;
42
+ import org .elasticsearch .script .BucketAggregationSelectorScript ;
41
43
import org .elasticsearch .script .ClassPermission ;
42
44
import org .elasticsearch .script .ExecutableScript ;
43
45
import org .elasticsearch .script .FilterScript ;
54
56
import java .security .PrivilegedAction ;
55
57
import java .text .ParseException ;
56
58
import java .util .ArrayList ;
59
+ import java .util .HashMap ;
57
60
import java .util .List ;
58
61
import java .util .Map ;
59
62
@@ -112,6 +115,17 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
112
115
} else if (context .instanceClazz .equals (ExecutableScript .class )) {
113
116
ExecutableScript .Factory factory = (p ) -> new ExpressionExecutableScript (expr , p );
114
117
return context .factoryClazz .cast (factory );
118
+ } else if (context .instanceClazz .equals (BucketAggregationScript .class )) {
119
+ return context .factoryClazz .cast (newBucketAggregationScriptFactory (expr ));
120
+ } else if (context .instanceClazz .equals (BucketAggregationSelectorScript .class )) {
121
+ BucketAggregationScript .Factory factory = newBucketAggregationScriptFactory (expr );
122
+ BucketAggregationSelectorScript .Factory wrappedFactory = parameters -> new BucketAggregationSelectorScript (parameters ) {
123
+ @ Override
124
+ public boolean execute () {
125
+ return factory .newInstance (getParams ()).execute () == 1.0 ;
126
+ }
127
+ };
128
+ return context .factoryClazz .cast (wrappedFactory );
115
129
} else if (context .instanceClazz .equals (FilterScript .class )) {
116
130
FilterScript .Factory factory = (p , lookup ) -> newFilterScript (expr , lookup , p );
117
131
return context .factoryClazz .cast (factory );
@@ -122,6 +136,37 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
122
136
throw new IllegalArgumentException ("expression engine does not know how to handle script context [" + context .name + "]" );
123
137
}
124
138
139
+ private static BucketAggregationScript .Factory newBucketAggregationScriptFactory (Expression expr ) {
140
+ return parameters -> {
141
+ ReplaceableConstDoubleValues [] functionValuesArray =
142
+ new ReplaceableConstDoubleValues [expr .variables .length ];
143
+ Map <String , ReplaceableConstDoubleValues > functionValuesMap = new HashMap <>();
144
+ for (int i = 0 ; i < expr .variables .length ; ++i ) {
145
+ functionValuesArray [i ] = new ReplaceableConstDoubleValues ();
146
+ functionValuesMap .put (expr .variables [i ], functionValuesArray [i ]);
147
+ }
148
+ return new BucketAggregationScript (parameters ) {
149
+ @ Override
150
+ public double execute () {
151
+ getParams ().forEach ((name , value ) -> {
152
+ ReplaceableConstDoubleValues placeholder = functionValuesMap .get (name );
153
+ if (placeholder == null ) {
154
+ throw new IllegalArgumentException ("Error using " + expr + ". " +
155
+ "The variable [" + name + "] does not exist in the executable expressions script." );
156
+ } else if (value instanceof Number == false ) {
157
+ throw new IllegalArgumentException ("Error using " + expr + ". " +
158
+ "Executable expressions scripts can only process numbers." +
159
+ " The variable [" + name + "] is not a number." );
160
+ } else {
161
+ placeholder .setValue (((Number ) value ).doubleValue ());
162
+ }
163
+ });
164
+ return expr .evaluate (functionValuesArray );
165
+ }
166
+ };
167
+ };
168
+ }
169
+
125
170
private SearchScript .LeafFactory newSearchScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
126
171
MapperService mapper = lookup .doc ().mapperService ();
127
172
// NOTE: if we need to do anything complicated with bindings in the future, we can just extend Bindings,
@@ -267,7 +312,7 @@ public void setDocument(int docid) {
267
312
};
268
313
};
269
314
}
270
-
315
+
271
316
private ScoreScript .LeafFactory newScoreScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
272
317
SearchScript .LeafFactory searchLeafFactory = newSearchScript (expr , lookup , vars );
273
318
return new ScoreScript .LeafFactory () {
@@ -284,17 +329,17 @@ public ScoreScript newInstance(LeafReaderContext ctx) throws IOException {
284
329
public double execute () {
285
330
return script .runAsDouble ();
286
331
}
287
-
332
+
288
333
@ Override
289
334
public void setDocument (int docid ) {
290
335
script .setDocument (docid );
291
336
}
292
-
337
+
293
338
@ Override
294
339
public void setScorer (Scorer scorer ) {
295
340
script .setScorer (scorer );
296
341
}
297
-
342
+
298
343
@ Override
299
344
public double get_score () {
300
345
return script .getScore ();
0 commit comments