Skip to content

Commit 2243838

Browse files
committed
aggs: Add percentiles method
This commit fixes #1045 by adding a percentiles method and correctly handle the `tdigest` and `hdr` case. Close #1045
1 parent 07d32ed commit 2243838

File tree

2 files changed

+74
-11
lines changed

2 files changed

+74
-11
lines changed

search_aggs_metrics_percentiles.go

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,24 @@ package elastic
1212
//
1313
// See: https://www.elastic.co/guide/en/elasticsearch/reference/6.7/search-aggregations-metrics-percentile-aggregation.html
1414
type PercentilesAggregation struct {
15-
field string
16-
script *Script
17-
format string
18-
missing interface{}
19-
subAggregations map[string]Aggregation
20-
meta map[string]interface{}
21-
percentiles []float64
22-
compression *float64
23-
estimator string
15+
field string
16+
script *Script
17+
format string
18+
missing interface{}
19+
subAggregations map[string]Aggregation
20+
meta map[string]interface{}
21+
percentiles []float64
22+
method string
23+
compression *float64
24+
numberOfSignificantValueDigits *int
25+
estimator string
2426
}
2527

2628
func NewPercentilesAggregation() *PercentilesAggregation {
2729
return &PercentilesAggregation{
2830
subAggregations: make(map[string]Aggregation),
2931
percentiles: make([]float64, 0),
32+
method: "tdigest",
3033
}
3134
}
3235

@@ -66,11 +69,22 @@ func (a *PercentilesAggregation) Percentiles(percentiles ...float64) *Percentile
6669
return a
6770
}
6871

72+
// Method is the percentiles method, which can be "tdigest" (default) or "hdr".
73+
func (a *PercentilesAggregation) Method(method string) *PercentilesAggregation {
74+
a.method = method
75+
return a
76+
}
77+
6978
func (a *PercentilesAggregation) Compression(compression float64) *PercentilesAggregation {
7079
a.compression = &compression
7180
return a
7281
}
7382

83+
func (a *PercentilesAggregation) NumberOfSignificantValueDigits(digits int) *PercentilesAggregation {
84+
a.numberOfSignificantValueDigits = &digits
85+
return a
86+
}
87+
7488
func (a *PercentilesAggregation) Estimator(estimator string) *PercentilesAggregation {
7589
a.estimator = estimator
7690
return a
@@ -115,8 +129,19 @@ func (a *PercentilesAggregation) Source() (interface{}, error) {
115129
if len(a.percentiles) > 0 {
116130
opts["percents"] = a.percentiles
117131
}
118-
if a.compression != nil {
119-
opts["compression"] = *a.compression
132+
switch a.method {
133+
case "tdigest":
134+
if c := a.compression; c != nil {
135+
opts[a.method] = map[string]interface{}{
136+
"compression": *c,
137+
}
138+
}
139+
case "hdr":
140+
if n := a.numberOfSignificantValueDigits; n != nil {
141+
opts[a.method] = map[string]interface{}{
142+
"number_of_significant_value_digits": *n,
143+
}
144+
}
120145
}
121146
if a.estimator != "" {
122147
opts["estimator"] = a.estimator

search_aggs_metrics_percentiles_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,41 @@ func TestPercentilesAggregationWithMetaData(t *testing.T) {
7979
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
8080
}
8181
}
82+
83+
func TestPercentilesAggregationWithCompression(t *testing.T) {
84+
agg := NewPercentilesAggregation().Field("load_time").Compression(200.0)
85+
src, err := agg.Source()
86+
if err != nil {
87+
t.Fatal(err)
88+
}
89+
data, err := json.Marshal(src)
90+
if err != nil {
91+
t.Fatalf("marshaling to JSON failed: %v", err)
92+
}
93+
got := string(data)
94+
expected := `{"percentiles":{"field":"load_time","tdigest":{"compression":200}}}`
95+
if got != expected {
96+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
97+
}
98+
}
99+
100+
func TestPercentilesAggregationWithNumberOfSignificantValueDigits(t *testing.T) {
101+
agg := NewPercentilesAggregation().
102+
Field("load_time").
103+
Percentiles(95, 99, 99.9).
104+
Method("hdr").
105+
NumberOfSignificantValueDigits(5)
106+
src, err := agg.Source()
107+
if err != nil {
108+
t.Fatal(err)
109+
}
110+
data, err := json.Marshal(src)
111+
if err != nil {
112+
t.Fatalf("marshaling to JSON failed: %v", err)
113+
}
114+
got := string(data)
115+
expected := `{"percentiles":{"field":"load_time","hdr":{"number_of_significant_value_digits":5},"percents":[95,99,99.9]}}`
116+
if got != expected {
117+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
118+
}
119+
}

0 commit comments

Comments
 (0)