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 7import "errors" 8 9// GeoBoundingBoxQuery allows to filter hits based on a point location using 10// a bounding box. 11// 12// For more details, see: 13// https://www.elastic.co/guide/en/elasticsearch/reference/6.7/query-dsl-geo-bounding-box-query.html 14type GeoBoundingBoxQuery struct { 15 name string 16 top *float64 17 left *float64 18 bottom *float64 19 right *float64 20 typ string 21 queryName string 22} 23 24// NewGeoBoundingBoxQuery creates and initializes a new GeoBoundingBoxQuery. 25func NewGeoBoundingBoxQuery(name string) *GeoBoundingBoxQuery { 26 return &GeoBoundingBoxQuery{ 27 name: name, 28 } 29} 30 31func (q *GeoBoundingBoxQuery) TopLeft(top, left float64) *GeoBoundingBoxQuery { 32 q.top = &top 33 q.left = &left 34 return q 35} 36 37func (q *GeoBoundingBoxQuery) TopLeftFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery { 38 return q.TopLeft(point.Lat, point.Lon) 39} 40 41func (q *GeoBoundingBoxQuery) BottomRight(bottom, right float64) *GeoBoundingBoxQuery { 42 q.bottom = &bottom 43 q.right = &right 44 return q 45} 46 47func (q *GeoBoundingBoxQuery) BottomRightFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery { 48 return q.BottomRight(point.Lat, point.Lon) 49} 50 51func (q *GeoBoundingBoxQuery) BottomLeft(bottom, left float64) *GeoBoundingBoxQuery { 52 q.bottom = &bottom 53 q.left = &left 54 return q 55} 56 57func (q *GeoBoundingBoxQuery) BottomLeftFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery { 58 return q.BottomLeft(point.Lat, point.Lon) 59} 60 61func (q *GeoBoundingBoxQuery) TopRight(top, right float64) *GeoBoundingBoxQuery { 62 q.top = &top 63 q.right = &right 64 return q 65} 66 67func (q *GeoBoundingBoxQuery) TopRightFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery { 68 return q.TopRight(point.Lat, point.Lon) 69} 70 71// Type sets the type of executing the geo bounding box. It can be either 72// memory or indexed. It defaults to memory. 73func (q *GeoBoundingBoxQuery) Type(typ string) *GeoBoundingBoxQuery { 74 q.typ = typ 75 return q 76} 77 78func (q *GeoBoundingBoxQuery) QueryName(queryName string) *GeoBoundingBoxQuery { 79 q.queryName = queryName 80 return q 81} 82 83// Source returns JSON for the function score query. 84func (q *GeoBoundingBoxQuery) Source() (interface{}, error) { 85 // { 86 // "geo_bounding_box" : { 87 // ... 88 // } 89 // } 90 91 if q.top == nil { 92 return nil, errors.New("geo_bounding_box requires top latitude to be set") 93 } 94 if q.bottom == nil { 95 return nil, errors.New("geo_bounding_box requires bottom latitude to be set") 96 } 97 if q.right == nil { 98 return nil, errors.New("geo_bounding_box requires right longitude to be set") 99 } 100 if q.left == nil { 101 return nil, errors.New("geo_bounding_box requires left longitude to be set") 102 } 103 104 source := make(map[string]interface{}) 105 params := make(map[string]interface{}) 106 source["geo_bounding_box"] = params 107 108 box := make(map[string]interface{}) 109 box["top_left"] = []float64{*q.left, *q.top} 110 box["bottom_right"] = []float64{*q.right, *q.bottom} 111 params[q.name] = box 112 113 if q.typ != "" { 114 params["type"] = q.typ 115 } 116 if q.queryName != "" { 117 params["_name"] = q.queryName 118 } 119 120 return source, nil 121} 122