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// GeoBoundsAggregation is a metric aggregation that computes the
8// bounding box containing all geo_point values for a field.
9// See: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-aggregations-metrics-geobounds-aggregation.html
10type GeoBoundsAggregation struct {
11	field           string
12	script          *Script
13	wrapLongitude   *bool
14	subAggregations map[string]Aggregation
15	meta            map[string]interface{}
16}
17
18func NewGeoBoundsAggregation() *GeoBoundsAggregation {
19	return &GeoBoundsAggregation{
20		subAggregations: make(map[string]Aggregation),
21	}
22}
23
24func (a *GeoBoundsAggregation) Field(field string) *GeoBoundsAggregation {
25	a.field = field
26	return a
27}
28
29func (a *GeoBoundsAggregation) Script(script *Script) *GeoBoundsAggregation {
30	a.script = script
31	return a
32}
33
34func (a *GeoBoundsAggregation) WrapLongitude(wrapLongitude bool) *GeoBoundsAggregation {
35	a.wrapLongitude = &wrapLongitude
36	return a
37}
38
39func (a *GeoBoundsAggregation) SubAggregation(name string, subAggregation Aggregation) *GeoBoundsAggregation {
40	a.subAggregations[name] = subAggregation
41	return a
42}
43
44// Meta sets the meta data to be included in the aggregation response.
45func (a *GeoBoundsAggregation) Meta(metaData map[string]interface{}) *GeoBoundsAggregation {
46	a.meta = metaData
47	return a
48}
49
50func (a *GeoBoundsAggregation) Source() (interface{}, error) {
51	// Example:
52	// {
53	//     "query" : {
54	//         "match" : { "business_type" : "shop" }
55	//     },
56	//     "aggs" : {
57	//         "viewport" : {
58	//             "geo_bounds" : {
59	//                 "field" : "location"
60	//                 "wrap_longitude" : "true"
61	//             }
62	//         }
63	//     }
64	// }
65	//
66	// This method returns only the { "geo_bounds" : { ... } } part.
67
68	source := make(map[string]interface{})
69	opts := make(map[string]interface{})
70	source["geo_bounds"] = opts
71
72	if a.field != "" {
73		opts["field"] = a.field
74	}
75	if a.script != nil {
76		src, err := a.script.Source()
77		if err != nil {
78			return nil, err
79		}
80		opts["script"] = src
81	}
82	if a.wrapLongitude != nil {
83		opts["wrap_longitude"] = *a.wrapLongitude
84	}
85
86	// AggregationBuilder (SubAggregations)
87	if len(a.subAggregations) > 0 {
88		aggsMap := make(map[string]interface{})
89		source["aggregations"] = aggsMap
90		for name, aggregate := range a.subAggregations {
91			src, err := aggregate.Source()
92			if err != nil {
93				return nil, err
94			}
95			aggsMap[name] = src
96		}
97	}
98
99	// Add Meta data if available
100	if len(a.meta) > 0 {
101		source["meta"] = a.meta
102	}
103
104	return source, nil
105}
106