Skip to content

Commit a6cbe6f

Browse files
lechnertecholivere
authored andcommitted
Add extended stats bucket for pipeline aggregations
This commit adds support for the extended stats bucket for pipeline aggregations. For details, see https://www.elastic.co/guide/en/elasticsearch/reference/6.5/search-aggregations-pipeline-stats-bucket-aggregation.html. See PR #1004.
1 parent f76f3a7 commit a6cbe6f

2 files changed

+171
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2012-present Oliver Eilhard. All rights reserved.
2+
// Use of this source code is governed by a MIT-license.
3+
// See http://olivere.mit-license.org/license.txt for details.
4+
5+
package elastic
6+
7+
// ExtendedStatsBucketAggregation is a sibling pipeline aggregation which calculates
8+
// a variety of stats across all bucket of a specified metric in a sibling aggregation.
9+
// The specified metric must be numeric and the sibling aggregation must
10+
// be a multi-bucket aggregation.
11+
//
12+
// This aggregation provides a few more statistics (sum of squares, standard deviation, etc)
13+
// compared to the stats_bucket aggregation.
14+
// For more details, see
15+
// https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-aggregations-pipeline-extended-stats-bucket-aggregation.html
16+
type ExtendedStatsBucketAggregation struct {
17+
format string
18+
gapPolicy string
19+
sigma *float32
20+
meta map[string]interface{}
21+
bucketsPaths []string
22+
}
23+
24+
// NewExtendedStatsBucketAggregation creates and initializes a new ExtendedStatsBucketAggregation.
25+
func NewExtendedStatsBucketAggregation() *ExtendedStatsBucketAggregation {
26+
return &ExtendedStatsBucketAggregation{
27+
bucketsPaths: make([]string, 0),
28+
}
29+
}
30+
31+
// Format to use on the output of this aggregation.
32+
func (s *ExtendedStatsBucketAggregation) Format(format string) *ExtendedStatsBucketAggregation {
33+
s.format = format
34+
return s
35+
}
36+
37+
// GapPolicy defines what should be done when a gap in the series is discovered.
38+
// Valid values include "insert_zeros" or "skip". Default is "insert_zeros".
39+
func (s *ExtendedStatsBucketAggregation) GapPolicy(gapPolicy string) *ExtendedStatsBucketAggregation {
40+
s.gapPolicy = gapPolicy
41+
return s
42+
}
43+
44+
// GapInsertZeros inserts zeros for gaps in the series.
45+
func (s *ExtendedStatsBucketAggregation) GapInsertZeros() *ExtendedStatsBucketAggregation {
46+
s.gapPolicy = "insert_zeros"
47+
return s
48+
}
49+
50+
// GapSkip skips gaps in the series.
51+
func (s *ExtendedStatsBucketAggregation) GapSkip() *ExtendedStatsBucketAggregation {
52+
s.gapPolicy = "skip"
53+
return s
54+
}
55+
56+
// Meta sets the meta data to be included in the aggregation response.
57+
func (s *ExtendedStatsBucketAggregation) Meta(metaData map[string]interface{}) *ExtendedStatsBucketAggregation {
58+
s.meta = metaData
59+
return s
60+
}
61+
62+
// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.
63+
func (s *ExtendedStatsBucketAggregation) BucketsPath(bucketsPaths ...string) *ExtendedStatsBucketAggregation {
64+
s.bucketsPaths = append(s.bucketsPaths, bucketsPaths...)
65+
return s
66+
}
67+
68+
// Sigma sets number of standard deviations above/below the mean to display
69+
func (s *ExtendedStatsBucketAggregation) Sigma(sigma float32) *ExtendedStatsBucketAggregation {
70+
s.sigma = &sigma
71+
return s
72+
}
73+
74+
// Source returns the a JSON-serializable interface.
75+
func (s *ExtendedStatsBucketAggregation) Source() (interface{}, error) {
76+
source := make(map[string]interface{})
77+
params := make(map[string]interface{})
78+
source["extended_stats_bucket"] = params
79+
80+
if s.format != "" {
81+
params["format"] = s.format
82+
}
83+
if s.gapPolicy != "" {
84+
params["gap_policy"] = s.gapPolicy
85+
}
86+
87+
// Add buckets paths
88+
switch len(s.bucketsPaths) {
89+
case 0:
90+
case 1:
91+
params["buckets_path"] = s.bucketsPaths[0]
92+
default:
93+
params["buckets_path"] = s.bucketsPaths
94+
}
95+
96+
// Add sigma is not zero or less
97+
if s.sigma != nil && *s.sigma >= 0 {
98+
params["sigma"] = *s.sigma
99+
}
100+
101+
// Add Meta data if available
102+
if len(s.meta) > 0 {
103+
source["meta"] = s.meta
104+
}
105+
106+
return source, nil
107+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2012-present Oliver Eilhard. All rights reserved.
2+
// Use of this source code is governed by a MIT-license.
3+
// See http://olivere.mit-license.org/license.txt for details.
4+
5+
package elastic
6+
7+
import (
8+
"encoding/json"
9+
"testing"
10+
)
11+
12+
func TestExtendedStatsBucketAggregationWithGapPolicy(t *testing.T) {
13+
agg := NewExtendedStatsBucketAggregation().BucketsPath("the_sum").GapPolicy("skip")
14+
src, err := agg.Source()
15+
if err != nil {
16+
t.Fatal(err)
17+
}
18+
data, err := json.Marshal(src)
19+
if err != nil {
20+
t.Fatalf("marshaling to JSON failed: %v", err)
21+
}
22+
got := string(data)
23+
expected := `{"extended_stats_bucket":{"buckets_path":"the_sum","gap_policy":"skip"}}`
24+
if got != expected {
25+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
26+
}
27+
}
28+
29+
func TestExtendedStatsBucketAggregation(t *testing.T) {
30+
31+
agg := NewExtendedStatsBucketAggregation().BucketsPath("another_test")
32+
src, err := agg.Source()
33+
if err != nil {
34+
t.Fatal(err)
35+
}
36+
data, err := json.Marshal(src)
37+
if err != nil {
38+
t.Fatalf("marshaling to JSON failed: %v", err)
39+
}
40+
got := string(data)
41+
expected := `{"extended_stats_bucket":{"buckets_path":"another_test"}}`
42+
if got != expected {
43+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
44+
}
45+
}
46+
47+
func TestExtendedStatsBucketAggregationWithSigma(t *testing.T) {
48+
agg := NewExtendedStatsBucketAggregation().BucketsPath("sigma_test")
49+
50+
agg.Sigma(3)
51+
src, err := agg.Source()
52+
if err != nil {
53+
t.Fatal(err)
54+
}
55+
data, err := json.Marshal(src)
56+
if err != nil {
57+
t.Fatalf("marshaling to JSON failed: %v", err)
58+
}
59+
got := string(data)
60+
expected := `{"extended_stats_bucket":{"buckets_path":"sigma_test","sigma":3}}`
61+
if got != expected {
62+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
63+
}
64+
}

0 commit comments

Comments
 (0)