mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-10-07 11:21:56 -04:00
Numeric and date ranges on both engines: bleve folds them from doc values, OpenSearch uses range and date_range aggregations. The proto gains BucketRange and bucketDefinition.ranges, the aggregation package the range parser (bounds are numbers or RFC3339 dates, one kind per aggregation, anything else is rejected), the kind of an option and the validation of ranges against the field type. Every requested range is answered in request order, an empty one with a count of zero, with no space answering too; size does not cut ranges, keyAsNumber sorts them by their lower bound. Range keys read from..to. AGG-04, 05 and 07 to 09 in the parity suite.
58 lines
1.9 KiB
Go
58 lines
1.9 KiB
Go
package aggregation
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
searchsvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/search/v0"
|
|
"github.com/opencloud-eu/opencloud/services/search/pkg/mapping"
|
|
)
|
|
|
|
// ValidateOptions holds aggregations to what the index can answer: a field it
|
|
// knows, a kind that fits the type of the field. fieldType returns the mapping
|
|
// type of a field, empty for one a client may not aggregate on.
|
|
func ValidateOptions(opts []*searchsvc.AggregationOption, fieldType func(string) string) error {
|
|
for _, opt := range opts {
|
|
field, t := opt.GetField(), fieldType(opt.GetField())
|
|
if t == "" {
|
|
return fmt.Errorf("unknown aggregation field %q", field)
|
|
}
|
|
switch KindOf(opt) {
|
|
case KindRange:
|
|
parsed, err := ParseRanges(field, opt.GetBucketDefinition().GetRanges())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := validateRangeField(field, t, parsed); err != nil {
|
|
return err
|
|
}
|
|
case KindTerms:
|
|
if err := validateTermsField(field, t); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateTermsField allows the types whose values are buckets as they are.
|
|
// The values of a date are instants, they aggregate in ranges.
|
|
func validateTermsField(field, fieldType string) error {
|
|
switch fieldType {
|
|
case mapping.TypeKeyword, mapping.TypeBool, mapping.TypeNumeric:
|
|
return nil
|
|
case mapping.TypeDatetime:
|
|
return fmt.Errorf("terms aggregation is not supported on date field %q; use bucketDefinition.ranges", field)
|
|
}
|
|
return fmt.Errorf("terms aggregation is not supported on field %q", field)
|
|
}
|
|
|
|
func validateRangeField(field, fieldType string, ranges Ranges) error {
|
|
if len(ranges.Numeric) > 0 && fieldType != mapping.TypeNumeric {
|
|
return fmt.Errorf("numeric ranges need a numeric field, %q is none", field)
|
|
}
|
|
if len(ranges.Dates) > 0 && fieldType != mapping.TypeDatetime {
|
|
return fmt.Errorf("date ranges need a date field, %q is none", field)
|
|
}
|
|
return nil
|
|
}
|