Elasticsearch: Support extended stats and percentiles in terms order by (#28910)

Adds support to the terms aggregation for ordering by percentiles and extended stats. 

Closes #5148

Co-authored-by: Giordano Ricci <grdnricci@gmail.com>
Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
This commit is contained in:
Chris Cowan
2021-01-15 12:10:16 +01:00
committed by GitHub
co-authored by Giordano Ricci Marcus Efraimsson
parent b32c4f34cd
commit 5088e2044a
10 changed files with 4516 additions and 99 deletions
+17 -4
View File
@@ -2,6 +2,7 @@ package elasticsearch
import (
"fmt"
"regexp"
"strconv"
"github.com/grafana/grafana/pkg/components/simplejson"
@@ -240,15 +241,27 @@ func addTermsAgg(aggBuilder es.AggBuilder, bucketAgg *BucketAgg, metrics []*Metr
}
if orderBy, err := bucketAgg.Settings.Get("orderBy").String(); err == nil {
a.Order[orderBy] = bucketAgg.Settings.Get("order").MustString("desc")
/*
The format for extended stats and percentiles is {metricId}[bucket_path]
for everything else it's just {metricId}, _count, _term, or _key
*/
metricIdRegex := regexp.MustCompile(`^(\d+)`)
metricId := metricIdRegex.FindString(orderBy)
if _, err := strconv.Atoi(orderBy); err == nil {
if len(metricId) > 0 {
for _, m := range metrics {
if m.ID == orderBy {
b.Metric(m.ID, m.Type, m.Field, nil)
if m.ID == metricId {
if m.Type == "count" {
a.Order["_count"] = bucketAgg.Settings.Get("order").MustString("desc")
} else {
a.Order[orderBy] = bucketAgg.Settings.Get("order").MustString("desc")
b.Metric(m.ID, m.Type, m.Field, nil)
}
break
}
}
} else {
a.Order[orderBy] = bucketAgg.Settings.Get("order").MustString("desc")
}
}
@@ -127,6 +127,80 @@ func TestExecuteTimeSeriesQuery(t *testing.T) {
So(avgAgg.Aggregation.Type, ShouldEqual, "avg")
})
Convey("With term agg and order by count metric agg", func() {
c := newFakeClient(5)
_, err := executeTsdbQuery(c, `{
"timeField": "@timestamp",
"bucketAggs": [
{
"type": "terms",
"field": "@host",
"id": "2",
"settings": { "size": "5", "order": "asc", "orderBy": "1" }
},
{ "type": "date_histogram", "field": "@timestamp", "id": "3" }
],
"metrics": [
{"type": "count", "id": "1" }
]
}`, from, to, 15*time.Second)
So(err, ShouldBeNil)
sr := c.multisearchRequests[0].Requests[0]
termsAgg := sr.Aggs[0].Aggregation.Aggregation.(*es.TermsAggregation)
So(termsAgg.Order["_count"], ShouldEqual, "asc")
})
Convey("With term agg and order by percentiles agg", func() {
c := newFakeClient(5)
_, err := executeTsdbQuery(c, `{
"timeField": "@timestamp",
"bucketAggs": [
{
"type": "terms",
"field": "@host",
"id": "2",
"settings": { "size": "5", "order": "asc", "orderBy": "1[95.0]" }
},
{ "type": "date_histogram", "field": "@timestamp", "id": "3" }
],
"metrics": [
{"type": "percentiles", "field": "@value", "id": "1", "settings": { "percents": ["95","99"] } }
]
}`, from, to, 15*time.Second)
So(err, ShouldBeNil)
sr := c.multisearchRequests[0].Requests[0]
orderByAgg := sr.Aggs[0].Aggregation.Aggs[0]
So(orderByAgg.Key, ShouldEqual, "1")
So(orderByAgg.Aggregation.Type, ShouldEqual, "percentiles")
})
Convey("With term agg and order by extended stats agg", func() {
c := newFakeClient(5)
_, err := executeTsdbQuery(c, `{
"timeField": "@timestamp",
"bucketAggs": [
{
"type": "terms",
"field": "@host",
"id": "2",
"settings": { "size": "5", "order": "asc", "orderBy": "1[std_deviation]" }
},
{ "type": "date_histogram", "field": "@timestamp", "id": "3" }
],
"metrics": [
{"type": "extended_stats", "field": "@value", "id": "1", "meta": { "std_deviation": true } }
]
}`, from, to, 15*time.Second)
So(err, ShouldBeNil)
sr := c.multisearchRequests[0].Requests[0]
orderByAgg := sr.Aggs[0].Aggregation.Aggs[0]
So(orderByAgg.Key, ShouldEqual, "1")
So(orderByAgg.Aggregation.Type, ShouldEqual, "extended_stats")
})
Convey("With term agg and order by term", func() {
c := newFakeClient(5)
_, err := executeTsdbQuery(c, `{