@@ -99,7 +99,10 @@ func (e *elasticsearchDataQuery) processQuery(q *Query, ms *es.MultiSearchReques
99
99
processDocumentQuery (q , b , from , to , defaultTimeField )
100
100
} else {
101
101
// Otherwise, it is a time series query and we process it
102
- processTimeSeriesQuery (q , b , from , to , defaultTimeField )
102
+ err := processTimeSeriesQuery (q , b , from , to , defaultTimeField )
103
+ if err != nil {
104
+ return err
105
+ }
103
106
}
104
107
105
108
return nil
@@ -164,12 +167,18 @@ func (bucketAgg BucketAgg) generateSettingsForDSL() map[string]interface{} {
164
167
return bucketAgg .Settings .MustMap ()
165
168
}
166
169
167
- func addDateHistogramAgg (aggBuilder es.AggBuilder , bucketAgg * BucketAgg , timeFrom , timeTo int64 , timeField string ) es.AggBuilder {
170
+ func addDateHistogramAgg (aggBuilder es.AggBuilder , bucketAgg * BucketAgg , timeFrom , timeTo int64 , timeField string ) ( es.AggBuilder , error ) {
168
171
// If no field is specified, use the time field
169
172
field := bucketAgg .Field
170
173
if field == "" {
171
174
field = timeField
172
175
}
176
+
177
+ // Validate that we have a valid field name to prevent downstream errors
178
+ if field == "" {
179
+ return aggBuilder , fmt .Errorf ("date_histogram aggregation '%s' has no field specified and datasource timeField is empty" , bucketAgg .ID )
180
+ }
181
+
173
182
aggBuilder .DateHistogram (bucketAgg .ID , field , func (a * es.DateHistogramAgg , b es.AggBuilder ) {
174
183
a .FixedInterval = bucketAgg .Settings .Get ("interval" ).MustString ("auto" )
175
184
a .MinDocCount = bucketAgg .Settings .Get ("min_doc_count" ).MustInt (0 )
@@ -204,7 +213,7 @@ func addDateHistogramAgg(aggBuilder es.AggBuilder, bucketAgg *BucketAgg, timeFro
204
213
aggBuilder = b
205
214
})
206
215
207
- return aggBuilder
216
+ return aggBuilder , nil
208
217
}
209
218
210
219
func addHistogramAgg (aggBuilder es.AggBuilder , bucketAgg * BucketAgg ) es.AggBuilder {
@@ -331,6 +340,30 @@ func isQueryWithError(query *Query) error {
331
340
if len (query .Metrics ) == 0 || ! (isLogsQuery (query ) || isDocumentQuery (query )) {
332
341
return fmt .Errorf ("invalid query, missing metrics and aggregations" )
333
342
}
343
+ } else {
344
+ // Validate bucket aggregations have valid fields where required
345
+ for _ , bucketAgg := range query .BucketAggs {
346
+ // Check which aggregation types require fields
347
+ switch bucketAgg .Type {
348
+ case dateHistType :
349
+ // For date_histogram, field can be empty (will use timeField as fallback)
350
+ // Validation will happen at query processing time
351
+ continue
352
+ case histogramType , termsType , geohashGridType , nestedType :
353
+ // These aggregation types require a field
354
+ if bucketAgg .Field == "" {
355
+ return fmt .Errorf ("invalid query, bucket aggregation '%s' (type: %s) is missing required field" , bucketAgg .ID , bucketAgg .Type )
356
+ }
357
+ case filtersType :
358
+ // Filters aggregations don't need a field
359
+ continue
360
+ default :
361
+ // For unknown aggregation types, be conservative and require field
362
+ if bucketAgg .Field == "" {
363
+ return fmt .Errorf ("invalid query, bucket aggregation '%s' (type: %s) is missing required field" , bucketAgg .ID , bucketAgg .Type )
364
+ }
365
+ }
366
+ }
334
367
}
335
368
return nil
336
369
}
@@ -380,7 +413,7 @@ func processDocumentQuery(q *Query, b *es.SearchRequestBuilder, from, to int64,
380
413
b .Size (stringToIntWithDefaultValue (metric .Settings .Get ("size" ).MustString (), defaultSize ))
381
414
}
382
415
383
- func processTimeSeriesQuery (q * Query , b * es.SearchRequestBuilder , from , to int64 , defaultTimeField string ) {
416
+ func processTimeSeriesQuery (q * Query , b * es.SearchRequestBuilder , from , to int64 , defaultTimeField string ) error {
384
417
aggBuilder := b .Agg ()
385
418
// Process buckets
386
419
// iterate backwards to create aggregations bottom-down
@@ -390,7 +423,11 @@ func processTimeSeriesQuery(q *Query, b *es.SearchRequestBuilder, from, to int64
390
423
)
391
424
switch bucketAgg .Type {
392
425
case dateHistType :
393
- aggBuilder = addDateHistogramAgg (aggBuilder , bucketAgg , from , to , defaultTimeField )
426
+ var err error
427
+ aggBuilder , err = addDateHistogramAgg (aggBuilder , bucketAgg , from , to , defaultTimeField )
428
+ if err != nil {
429
+ return err
430
+ }
394
431
case histogramType :
395
432
aggBuilder = addHistogramAgg (aggBuilder , bucketAgg )
396
433
case filtersType :
@@ -471,6 +508,8 @@ func processTimeSeriesQuery(q *Query, b *es.SearchRequestBuilder, from, to int64
471
508
})
472
509
}
473
510
}
511
+
512
+ return nil
474
513
}
475
514
476
515
func stringToIntWithDefaultValue (valueStr string , defaultValue int ) int {
0 commit comments