39
39
import org .elasticsearch .index .query .QueryBuilder ;
40
40
import org .elasticsearch .index .query .RangeQueryBuilder ;
41
41
import org .elasticsearch .index .query .TermQueryBuilder ;
42
+ import org .elasticsearch .index .query .TermsQueryBuilder ;
42
43
import org .elasticsearch .script .ScriptService ;
43
44
import org .elasticsearch .search .aggregations .AggregationBuilder ;
44
45
import org .elasticsearch .search .aggregations .AggregatorFactories ;
66
67
import java .io .IOException ;
67
68
import java .util .ArrayList ;
68
69
import java .util .Arrays ;
70
+ import java .util .Collections ;
69
71
import java .util .HashSet ;
70
72
import java .util .List ;
71
73
import java .util .Objects ;
@@ -276,91 +278,38 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
276
278
rewriteQuery (((BoostingQueryBuilder )builder ).positiveQuery (), jobCaps ));
277
279
} else if (builder .getWriteableName ().equals (DisMaxQueryBuilder .NAME )) {
278
280
DisMaxQueryBuilder rewritten = new DisMaxQueryBuilder ();
279
- ((DisMaxQueryBuilder )builder ).innerQueries ().forEach (query -> rewritten .add (rewriteQuery (query , jobCaps )));
281
+ ((DisMaxQueryBuilder ) builder ).innerQueries ().forEach (query -> rewritten .add (rewriteQuery (query , jobCaps )));
280
282
return rewritten ;
281
- } else if (builder .getWriteableName ().equals (RangeQueryBuilder .NAME ) || builder .getWriteableName ().equals (TermQueryBuilder .NAME )) {
282
-
283
- String fieldName = builder .getWriteableName ().equals (RangeQueryBuilder .NAME )
284
- ? ((RangeQueryBuilder )builder ).fieldName ()
285
- : ((TermQueryBuilder )builder ).fieldName ();
286
-
287
- List <String > incorrectTimeZones = new ArrayList <>();
288
- List <String > rewrittenFieldName = jobCaps .stream ()
289
- // We only care about job caps that have the query's target field
290
- .filter (caps -> caps .getFieldCaps ().keySet ().contains (fieldName ))
291
- .map (caps -> {
292
- RollupJobCaps .RollupFieldCaps fieldCaps = caps .getFieldCaps ().get (fieldName );
293
- return fieldCaps .getAggs ().stream ()
294
- // For now, we only allow filtering on grouping fields
295
- .filter (agg -> {
296
- String type = (String )agg .get (RollupField .AGG );
297
-
298
- // If the cap is for a date_histo, and the query is a range, the timezones need to match
299
- if (type .equals (DateHistogramAggregationBuilder .NAME ) && builder instanceof RangeQueryBuilder ) {
300
- String timeZone = ((RangeQueryBuilder )builder ).timeZone ();
301
-
302
- // Many range queries don't include the timezone because the default is UTC, but the query
303
- // builder will return null so we need to set it here
304
- if (timeZone == null ) {
305
- timeZone = DateTimeZone .UTC .toString ();
306
- }
307
- boolean matchingTZ = ((String )agg .get (DateHistoGroupConfig .TIME_ZONE .getPreferredName ()))
308
- .equalsIgnoreCase (timeZone );
309
- if (matchingTZ == false ) {
310
- incorrectTimeZones .add ((String )agg .get (DateHistoGroupConfig .TIME_ZONE .getPreferredName ()));
311
- }
312
- return matchingTZ ;
313
- }
314
- // Otherwise just make sure it's one of the three groups
315
- return type .equals (TermsAggregationBuilder .NAME )
316
- || type .equals (DateHistogramAggregationBuilder .NAME )
317
- || type .equals (HistogramAggregationBuilder .NAME );
318
- })
319
- // Rewrite the field name to our convention (e.g. "foo" -> "date_histogram.foo.timestamp")
320
- .map (agg -> {
321
- if (agg .get (RollupField .AGG ).equals (DateHistogramAggregationBuilder .NAME )) {
322
- return RollupField .formatFieldName (fieldName , (String )agg .get (RollupField .AGG ), RollupField .TIMESTAMP );
323
- } else {
324
- return RollupField .formatFieldName (fieldName , (String )agg .get (RollupField .AGG ), RollupField .VALUE );
325
- }
326
- })
327
- .collect (Collectors .toList ());
328
- })
329
- .distinct ()
330
- .collect (ArrayList ::new , List ::addAll , List ::addAll );
331
-
332
- if (rewrittenFieldName .isEmpty ()) {
333
- if (incorrectTimeZones .isEmpty ()) {
334
- throw new IllegalArgumentException ("Field [" + fieldName + "] in [" + builder .getWriteableName ()
335
- + "] query is not available in selected rollup indices, cannot query." );
336
- } else {
337
- throw new IllegalArgumentException ("Field [" + fieldName + "] in [" + builder .getWriteableName ()
338
- + "] query was found in rollup indices, but requested timezone is not compatible. Options include: "
339
- + incorrectTimeZones );
340
- }
283
+ } else if (builder .getWriteableName ().equals (RangeQueryBuilder .NAME )) {
284
+ RangeQueryBuilder range = (RangeQueryBuilder ) builder ;
285
+ String fieldName = range .fieldName ();
286
+ // Many range queries don't include the timezone because the default is UTC, but the query
287
+ // builder will return null so we need to set it here
288
+ String timeZone = range .timeZone () == null ? DateTimeZone .UTC .toString () : range .timeZone ();
289
+
290
+ String rewrittenFieldName = rewriteFieldName (jobCaps , RangeQueryBuilder .NAME , fieldName , timeZone );
291
+ RangeQueryBuilder rewritten = new RangeQueryBuilder (rewrittenFieldName )
292
+ .from (range .from ())
293
+ .to (range .to ())
294
+ .includeLower (range .includeLower ())
295
+ .includeUpper (range .includeUpper ());
296
+ if (range .timeZone () != null ) {
297
+ rewritten .timeZone (range .timeZone ());
341
298
}
342
-
343
- if (rewrittenFieldName .size () > 1 ) {
344
- throw new IllegalArgumentException ("Ambiguous field name resolution when mapping to rolled fields. Field name [" +
345
- fieldName + "] was mapped to: [" + Strings .collectionToDelimitedString (rewrittenFieldName , "," ) + "]." );
299
+ if (range .format () != null ) {
300
+ rewritten .format (range .format ());
346
301
}
347
-
348
- //Note: instanceof here to make casting checks happier
349
- if (builder instanceof RangeQueryBuilder ) {
350
- RangeQueryBuilder rewritten = new RangeQueryBuilder (rewrittenFieldName .get (0 ));
351
- RangeQueryBuilder original = (RangeQueryBuilder )builder ;
352
- rewritten .from (original .from ());
353
- rewritten .to (original .to ());
354
- if (original .timeZone () != null ) {
355
- rewritten .timeZone (original .timeZone ());
356
- }
357
- rewritten .includeLower (original .includeLower ());
358
- rewritten .includeUpper (original .includeUpper ());
359
- return rewritten ;
360
- } else {
361
- return new TermQueryBuilder (rewrittenFieldName .get (0 ), ((TermQueryBuilder )builder ).value ());
362
- }
363
-
302
+ return rewritten ;
303
+ } else if (builder .getWriteableName ().equals (TermQueryBuilder .NAME )) {
304
+ TermQueryBuilder term = (TermQueryBuilder ) builder ;
305
+ String fieldName = term .fieldName ();
306
+ String rewrittenFieldName = rewriteFieldName (jobCaps , TermQueryBuilder .NAME , fieldName , null );
307
+ return new TermQueryBuilder (rewrittenFieldName , term .value ());
308
+ } else if (builder .getWriteableName ().equals (TermsQueryBuilder .NAME )) {
309
+ TermsQueryBuilder terms = (TermsQueryBuilder ) builder ;
310
+ String fieldName = terms .fieldName ();
311
+ String rewrittenFieldName = rewriteFieldName (jobCaps , TermQueryBuilder .NAME , fieldName , null );
312
+ return new TermsQueryBuilder (rewrittenFieldName , terms .values ());
364
313
} else if (builder .getWriteableName ().equals (MatchAllQueryBuilder .NAME )) {
365
314
// no-op
366
315
return builder ;
@@ -369,6 +318,64 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
369
318
}
370
319
}
371
320
321
+ private static String rewriteFieldName (Set <RollupJobCaps > jobCaps ,
322
+ String builderName ,
323
+ String fieldName ,
324
+ String timeZone ) {
325
+ List <String > incompatibleTimeZones = timeZone == null ? Collections .emptyList () : new ArrayList <>();
326
+ List <String > rewrittenFieldNames = jobCaps .stream ()
327
+ // We only care about job caps that have the query's target field
328
+ .filter (caps -> caps .getFieldCaps ().keySet ().contains (fieldName ))
329
+ .map (caps -> {
330
+ RollupJobCaps .RollupFieldCaps fieldCaps = caps .getFieldCaps ().get (fieldName );
331
+ return fieldCaps .getAggs ().stream ()
332
+ // For now, we only allow filtering on grouping fields
333
+ .filter (agg -> {
334
+ String type = (String )agg .get (RollupField .AGG );
335
+
336
+ // If the cap is for a date_histo, and the query is a range, the timezones need to match
337
+ if (type .equals (DateHistogramAggregationBuilder .NAME ) && timeZone != null ) {
338
+ boolean matchingTZ = ((String )agg .get (DateHistoGroupConfig .TIME_ZONE .getPreferredName ()))
339
+ .equalsIgnoreCase (timeZone );
340
+ if (matchingTZ == false ) {
341
+ incompatibleTimeZones .add ((String )agg .get (DateHistoGroupConfig .TIME_ZONE .getPreferredName ()));
342
+ }
343
+ return matchingTZ ;
344
+ }
345
+ // Otherwise just make sure it's one of the three groups
346
+ return type .equals (TermsAggregationBuilder .NAME )
347
+ || type .equals (DateHistogramAggregationBuilder .NAME )
348
+ || type .equals (HistogramAggregationBuilder .NAME );
349
+ })
350
+ // Rewrite the field name to our convention (e.g. "foo" -> "date_histogram.foo.timestamp")
351
+ .map (agg -> {
352
+ if (agg .get (RollupField .AGG ).equals (DateHistogramAggregationBuilder .NAME )) {
353
+ return RollupField .formatFieldName (fieldName , (String )agg .get (RollupField .AGG ), RollupField .TIMESTAMP );
354
+ } else {
355
+ return RollupField .formatFieldName (fieldName , (String )agg .get (RollupField .AGG ), RollupField .VALUE );
356
+ }
357
+ })
358
+ .collect (Collectors .toList ());
359
+ })
360
+ .distinct ()
361
+ .collect (ArrayList ::new , List ::addAll , List ::addAll );
362
+ if (rewrittenFieldNames .isEmpty ()) {
363
+ if (incompatibleTimeZones .isEmpty ()) {
364
+ throw new IllegalArgumentException ("Field [" + fieldName + "] in [" + builderName
365
+ + "] query is not available in selected rollup indices, cannot query." );
366
+ } else {
367
+ throw new IllegalArgumentException ("Field [" + fieldName + "] in [" + builderName
368
+ + "] query was found in rollup indices, but requested timezone is not compatible. Options include: "
369
+ + incompatibleTimeZones );
370
+ }
371
+ } else if (rewrittenFieldNames .size () > 1 ) {
372
+ throw new IllegalArgumentException ("Ambiguous field name resolution when mapping to rolled fields. Field name [" +
373
+ fieldName + "] was mapped to: [" + Strings .collectionToDelimitedString (rewrittenFieldNames , "," ) + "]." );
374
+ } else {
375
+ return rewrittenFieldNames .get (0 );
376
+ }
377
+ }
378
+
372
379
static RollupSearchContext separateIndices (String [] indices , ImmutableOpenMap <String , IndexMetaData > indexMetaData ) {
373
380
374
381
if (indices .length == 0 ) {
0 commit comments