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
5package elastic
6
7// SumBucketAggregation is a sibling pipeline aggregation which calculates
8// the sum across all buckets 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// For more details, see
13// https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-aggregations-pipeline-sum-bucket-aggregation.html
14type SumBucketAggregation struct {
15	format    string
16	gapPolicy string
17
18	subAggregations map[string]Aggregation
19	meta            map[string]interface{}
20	bucketsPaths    []string
21}
22
23// NewSumBucketAggregation creates and initializes a new SumBucketAggregation.
24func NewSumBucketAggregation() *SumBucketAggregation {
25	return &SumBucketAggregation{
26		subAggregations: make(map[string]Aggregation),
27		bucketsPaths:    make([]string, 0),
28	}
29}
30
31func (a *SumBucketAggregation) Format(format string) *SumBucketAggregation {
32	a.format = format
33	return a
34}
35
36// GapPolicy defines what should be done when a gap in the series is discovered.
37// Valid values include "insert_zeros" or "skip". Default is "insert_zeros".
38func (a *SumBucketAggregation) GapPolicy(gapPolicy string) *SumBucketAggregation {
39	a.gapPolicy = gapPolicy
40	return a
41}
42
43// GapInsertZeros inserts zeros for gaps in the series.
44func (a *SumBucketAggregation) GapInsertZeros() *SumBucketAggregation {
45	a.gapPolicy = "insert_zeros"
46	return a
47}
48
49// GapSkip skips gaps in the series.
50func (a *SumBucketAggregation) GapSkip() *SumBucketAggregation {
51	a.gapPolicy = "skip"
52	return a
53}
54
55// SubAggregation adds a sub-aggregation to this aggregation.
56func (a *SumBucketAggregation) SubAggregation(name string, subAggregation Aggregation) *SumBucketAggregation {
57	a.subAggregations[name] = subAggregation
58	return a
59}
60
61// Meta sets the meta data to be included in the aggregation response.
62func (a *SumBucketAggregation) Meta(metaData map[string]interface{}) *SumBucketAggregation {
63	a.meta = metaData
64	return a
65}
66
67// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.
68func (a *SumBucketAggregation) BucketsPath(bucketsPaths ...string) *SumBucketAggregation {
69	a.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)
70	return a
71}
72
73func (a *SumBucketAggregation) Source() (interface{}, error) {
74	source := make(map[string]interface{})
75	params := make(map[string]interface{})
76	source["sum_bucket"] = params
77
78	if a.format != "" {
79		params["format"] = a.format
80	}
81	if a.gapPolicy != "" {
82		params["gap_policy"] = a.gapPolicy
83	}
84
85	// Add buckets paths
86	switch len(a.bucketsPaths) {
87	case 0:
88	case 1:
89		params["buckets_path"] = a.bucketsPaths[0]
90	default:
91		params["buckets_path"] = a.bucketsPaths
92	}
93
94	// AggregationBuilder (SubAggregations)
95	if len(a.subAggregations) > 0 {
96		aggsMap := make(map[string]interface{})
97		source["aggregations"] = aggsMap
98		for name, aggregate := range a.subAggregations {
99			src, err := aggregate.Source()
100			if err != nil {
101				return nil, err
102			}
103			aggsMap[name] = src
104		}
105	}
106
107	// Add Meta data if available
108	if len(a.meta) > 0 {
109		source["meta"] = a.meta
110	}
111
112	return source, nil
113}
114