elastic icon indicating copy to clipboard operation
elastic copied to clipboard

Geo shape query

Open slifer2015 opened this issue 5 years ago • 3 comments

Hi and thanks for awesome library u seem missing the geo shape query can u add the support for it

slifer2015 avatar Oct 13 '18 14:10 slifer2015

GeoShapeQuery was last discussed in #276. It turned out that it was the most complex thing we'd had to do if you had all the builders that are also supported by the Java source.

A workaround is to use e.g. RawQuery and or create your own query by implementing the Query interface.

olivere avatar Oct 14 '18 16:10 olivere

I noticed a while ago that geo query wasn't implemented and implemented my own. It's by no means comprehensive, but it should get you started, and it follows your code patterns It's just one file, so please excuse me for not submitting a formal PR.. We've been using it for about a year now, so it' s compatible with both ES5 and ES6.

package your_package

// GeoShapeQuery extends the elastic package in golang, which does not currently implement geo_shape querying.
type GeoShapeQuery struct {
	path    string
	shape   string
	point   []float64
	polygon [][][]float64
}

// NewGeoShapeQuery creates a new elasticsearch geo_shape query
func NewGeoShapeQuery(path string) *GeoShapeQuery {
	return &GeoShapeQuery{
		path: path,
	}
}

// Shape specifies what shape this query represents
func (q *GeoShapeQuery) Shape(shape string) *GeoShapeQuery {
	q.shape = shape
	return q
}

// AddPoint adds a point
func (q *GeoShapeQuery) AddPoint(point []float64) *GeoShapeQuery {
	q.point = point
	return q
}

// AddPolygon adds a polygon
func (q *GeoShapeQuery) AddPolygon(polygon [][][]float64) *GeoShapeQuery {
	q.polygon = polygon
	return q
}

// Source returns JSON for the query.
func (q *GeoShapeQuery) Source() (interface{}, error) {
	source := make(map[string]interface{})

	params := make(map[string]interface{})
	source["geo_shape"] = params

	shape := make(map[string]interface{})
	params[q.path] = shape

	shapeDef := make(map[string]interface{})
	shape["shape"] = shapeDef

	shapeDef["type"] = q.shape
	if q.shape == "point" {
		shapeDef["coordinates"] = q.point
	} else if q.shape == "polygon" {
		shapeDef["coordinates"] = q.polygon
	}

	return source, nil
}

Example usage:

			if feature.Geometry.IsPoint() {
				aoiQueries = append(aoiQueries, NewGeoShapeQuery(aoiPath).Shape(strings.ToLower(pointType)).AddPoint(feature.Geometry.Point))
			} else if feature.Geometry.IsPolygon() {
				aoiQueries = append(aoiQueries, NewGeoShapeQuery(aoiPath).Shape(strings.ToLower(polygonType)).AddPolygon(feature.Geometry.Polygon))
			}

cmitchell avatar Oct 15 '18 12:10 cmitchell

Thanks @cmitchell. That's a good starter. What I really want is a GeoShapeBuilder for points, circles, polygons etc., just like in the Java source (something like this). But that's a lot of work--though it's just a builder, so not hard in terms of complexity. That [][][]float64 is correct, but it makes me shudder ;-)

olivere avatar Oct 15 '18 13:10 olivere