Skip to content

Commit 6a57f27

Browse files
committed
Fix GitHub issue #152
1 parent 976a3dd commit 6a57f27

File tree

3 files changed

+361
-7
lines changed

3 files changed

+361
-7
lines changed

pkg/quickwit/data_query.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ func (e *elasticsearchDataQuery) processQuery(q *Query, ms *es.MultiSearchReques
9999
processDocumentQuery(q, b, from, to, defaultTimeField)
100100
} else {
101101
// 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+
}
103106
}
104107

105108
return nil
@@ -164,12 +167,18 @@ func (bucketAgg BucketAgg) generateSettingsForDSL() map[string]interface{} {
164167
return bucketAgg.Settings.MustMap()
165168
}
166169

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) {
168171
// If no field is specified, use the time field
169172
field := bucketAgg.Field
170173
if field == "" {
171174
field = timeField
172175
}
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+
173182
aggBuilder.DateHistogram(bucketAgg.ID, field, func(a *es.DateHistogramAgg, b es.AggBuilder) {
174183
a.FixedInterval = bucketAgg.Settings.Get("interval").MustString("auto")
175184
a.MinDocCount = bucketAgg.Settings.Get("min_doc_count").MustInt(0)
@@ -204,7 +213,7 @@ func addDateHistogramAgg(aggBuilder es.AggBuilder, bucketAgg *BucketAgg, timeFro
204213
aggBuilder = b
205214
})
206215

207-
return aggBuilder
216+
return aggBuilder, nil
208217
}
209218

210219
func addHistogramAgg(aggBuilder es.AggBuilder, bucketAgg *BucketAgg) es.AggBuilder {
@@ -331,6 +340,30 @@ func isQueryWithError(query *Query) error {
331340
if len(query.Metrics) == 0 || !(isLogsQuery(query) || isDocumentQuery(query)) {
332341
return fmt.Errorf("invalid query, missing metrics and aggregations")
333342
}
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+
}
334367
}
335368
return nil
336369
}
@@ -380,7 +413,7 @@ func processDocumentQuery(q *Query, b *es.SearchRequestBuilder, from, to int64,
380413
b.Size(stringToIntWithDefaultValue(metric.Settings.Get("size").MustString(), defaultSize))
381414
}
382415

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 {
384417
aggBuilder := b.Agg()
385418
// Process buckets
386419
// iterate backwards to create aggregations bottom-down
@@ -390,7 +423,11 @@ func processTimeSeriesQuery(q *Query, b *es.SearchRequestBuilder, from, to int64
390423
)
391424
switch bucketAgg.Type {
392425
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+
}
394431
case histogramType:
395432
aggBuilder = addHistogramAgg(aggBuilder, bucketAgg)
396433
case filtersType:
@@ -471,6 +508,8 @@ func processTimeSeriesQuery(q *Query, b *es.SearchRequestBuilder, from, to int64
471508
})
472509
}
473510
}
511+
512+
return nil
474513
}
475514

476515
func stringToIntWithDefaultValue(valueStr string, defaultValue int) int {

pkg/quickwit/timestamp_infos.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,15 @@ func FindTimestampFormat(timestampFieldName string, parentName *string, fieldMap
112112
if nil != parentName {
113113
fieldName = fmt.Sprintf("%s.%s", *parentName, fieldName)
114114
}
115-
116115
if field.Type == "datetime" && fieldName == timestampFieldName && nil != field.OutputFormat {
117116
return *field.OutputFormat, true
118117
} else if field.Type == "object" && nil != field.FieldMappings {
119-
return FindTimestampFormat(timestampFieldName, &field.Name, field.FieldMappings)
118+
if result, found := FindTimestampFormat(timestampFieldName, &field.Name, field.FieldMappings); found {
119+
return result, true
120+
}
120121
}
121122
}
122123

124+
qwlog.Debug(fmt.Sprintf("FindTimestampFormat: no match found for %s", timestampFieldName))
123125
return "", false
124126
}

0 commit comments

Comments
 (0)