1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// Copyright 2012-2015 Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.
package elastic
// GeoDistanceAggregation is a multi-bucket aggregation that works on geo_point fields
// and conceptually works very similar to the range aggregation.
// The user can define a point of origin and a set of distance range buckets.
// The aggregation evaluate the distance of each document value from
// the origin point and determines the buckets it belongs to based on
// the ranges (a document belongs to a bucket if the distance between the
// document and the origin falls within the distance range of the bucket).
// See: http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-geodistance-aggregation.html
type GeoDistanceAggregation struct {
field string
unit string
distanceType string
point string
ranges []geoDistAggRange
subAggregations map[string]Aggregation
}
type geoDistAggRange struct {
Key string
From interface{}
To interface{}
}
func NewGeoDistanceAggregation() GeoDistanceAggregation {
a := GeoDistanceAggregation{
subAggregations: make(map[string]Aggregation),
ranges: make([]geoDistAggRange, 0),
}
return a
}
func (a GeoDistanceAggregation) Field(field string) GeoDistanceAggregation {
a.field = field
return a
}
func (a GeoDistanceAggregation) Unit(unit string) GeoDistanceAggregation {
a.unit = unit
return a
}
func (a GeoDistanceAggregation) DistanceType(distanceType string) GeoDistanceAggregation {
a.distanceType = distanceType
return a
}
func (a GeoDistanceAggregation) Point(latLon string) GeoDistanceAggregation {
a.point = latLon
return a
}
func (a GeoDistanceAggregation) SubAggregation(name string, subAggregation Aggregation) GeoDistanceAggregation {
a.subAggregations[name] = subAggregation
return a
}
func (a GeoDistanceAggregation) AddRange(from, to interface{}) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{From: from, To: to})
return a
}
func (a GeoDistanceAggregation) AddRangeWithKey(key string, from, to interface{}) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{Key: key, From: from, To: to})
return a
}
func (a GeoDistanceAggregation) AddUnboundedTo(from float64) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{From: from, To: nil})
return a
}
func (a GeoDistanceAggregation) AddUnboundedToWithKey(key string, from float64) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{Key: key, From: from, To: nil})
return a
}
func (a GeoDistanceAggregation) AddUnboundedFrom(to float64) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{From: nil, To: to})
return a
}
func (a GeoDistanceAggregation) AddUnboundedFromWithKey(key string, to float64) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{Key: key, From: nil, To: to})
return a
}
func (a GeoDistanceAggregation) Between(from, to interface{}) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{From: from, To: to})
return a
}
func (a GeoDistanceAggregation) BetweenWithKey(key string, from, to interface{}) GeoDistanceAggregation {
a.ranges = append(a.ranges, geoDistAggRange{Key: key, From: from, To: to})
return a
}
func (a GeoDistanceAggregation) Source() interface{} {
// Example:
// {
// "aggs" : {
// "rings_around_amsterdam" : {
// "geo_distance" : {
// "field" : "location",
// "origin" : "52.3760, 4.894",
// "ranges" : [
// { "to" : 100 },
// { "from" : 100, "to" : 300 },
// { "from" : 300 }
// ]
// }
// }
// }
// }
//
// This method returns only the { "range" : { ... } } part.
source := make(map[string]interface{})
opts := make(map[string]interface{})
source["geo_distance"] = opts
if a.field != "" {
opts["field"] = a.field
}
if a.unit != "" {
opts["unit"] = a.unit
}
if a.distanceType != "" {
opts["distance_type"] = a.distanceType
}
if a.point != "" {
opts["origin"] = a.point
}
ranges := make([]interface{}, 0)
for _, ent := range a.ranges {
r := make(map[string]interface{})
if ent.Key != "" {
r["key"] = ent.Key
}
if ent.From != nil {
switch from := ent.From.(type) {
case int, int16, int32, int64, float32, float64:
r["from"] = from
case *int, *int16, *int32, *int64, *float32, *float64:
r["from"] = from
case string:
r["from"] = from
}
}
if ent.To != nil {
switch to := ent.To.(type) {
case int, int16, int32, int64, float32, float64:
r["to"] = to
case *int, *int16, *int32, *int64, *float32, *float64:
r["to"] = to
case string:
r["to"] = to
}
}
ranges = append(ranges, r)
}
opts["ranges"] = ranges
// AggregationBuilder (SubAggregations)
if len(a.subAggregations) > 0 {
aggsMap := make(map[string]interface{})
source["aggregations"] = aggsMap
for name, aggregate := range a.subAggregations {
aggsMap[name] = aggregate.Source()
}
}
return source
}
|