2015-05-05 02:27:52 -04:00
|
|
|
[[query-dsl-geo-bounding-box-query]]
|
2015-06-03 19:59:22 -04:00
|
|
|
=== Geo Bounding Box Query
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2015-05-05 02:27:52 -04:00
|
|
|
A query allowing to filter hits based on a point location using a
|
2013-08-28 19:24:34 -04:00
|
|
|
bounding box. Assuming the following indexed document:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2019-01-14 16:08:01 -05:00
|
|
|
PUT /my_locations?include_type_name=true
|
2016-05-24 05:58:43 -04:00
|
|
|
{
|
|
|
|
"mappings": {
|
2017-12-14 11:47:53 -05:00
|
|
|
"_doc": {
|
2016-05-24 05:58:43 -04:00
|
|
|
"properties": {
|
|
|
|
"pin": {
|
|
|
|
"properties": {
|
|
|
|
"location": {
|
|
|
|
"type": "geo_point"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-14 11:47:53 -05:00
|
|
|
PUT /my_locations/_doc/1
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
|
|
|
"pin" : {
|
|
|
|
"location" : {
|
|
|
|
"lat" : 40.12,
|
|
|
|
"lon" : -71.34
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
|
|
|
// TESTSETUP
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
Then the following simple query can be executed with a
|
|
|
|
`geo_bounding_box` filter:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : {
|
|
|
|
"lat" : 40.73,
|
|
|
|
"lon" : -74.1
|
|
|
|
},
|
|
|
|
"bottom_right" : {
|
|
|
|
"lat" : 40.01,
|
|
|
|
"lon" : -71.12
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
2016-05-12 06:58:22 -04:00
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2015-08-07 16:55:22 -04:00
|
|
|
[float]
|
|
|
|
==== Query Options
|
|
|
|
|
|
|
|
[cols="<,<",options="header",]
|
|
|
|
|=======================================================================
|
|
|
|
|Option |Description
|
|
|
|
|`_name` |Optional name field to identify the filter
|
|
|
|
|
2016-04-28 08:10:59 -04:00
|
|
|
|`validation_method` |Set to `IGNORE_MALFORMED` to
|
|
|
|
accept geo points with invalid latitude or longitude, set to
|
|
|
|
`COERCE` to also try to infer correct latitude or longitude. (default is `STRICT`).
|
2015-08-07 16:55:22 -04:00
|
|
|
|
|
|
|
|`type` |Set to one of `indexed` or `memory` to defines whether this filter will
|
2015-08-18 06:20:00 -04:00
|
|
|
be executed in memory or indexed. See <<geo-bbox-type,Type>> below for further details
|
2015-08-07 16:55:22 -04:00
|
|
|
Default is `memory`.
|
|
|
|
|=======================================================================
|
|
|
|
|
2013-08-28 19:24:34 -04:00
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Accepted Formats
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
In much the same way the geo_point type can accept different
|
2016-10-05 08:54:32 -04:00
|
|
|
representations of the geo point, the filter can accept it as well:
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
===== Lat Lon As Properties
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : {
|
|
|
|
"lat" : 40.73,
|
|
|
|
"lon" : -74.1
|
|
|
|
},
|
|
|
|
"bottom_right" : {
|
|
|
|
"lat" : 40.01,
|
|
|
|
"lon" : -71.12
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
===== Lat Lon As Array
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
Format in `[lon, lat]`, note, the order of lon/lat here in order to
|
|
|
|
conform with http://geojson.org/[GeoJSON].
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : [-74.1, 40.73],
|
|
|
|
"bottom_right" : [-71.12, 40.01]
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
2016-05-12 06:58:22 -04:00
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
===== Lat Lon As String
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
Format in `lat,lon`.
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : "40.73, -74.1",
|
|
|
|
"bottom_right" : "40.01, -71.12"
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
2016-05-12 06:58:22 -04:00
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
2016-05-24 05:58:43 -04:00
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2017-12-06 12:58:20 -05:00
|
|
|
[float]
|
|
|
|
===== Bounding Box as Well-Known Text (WKT)
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
GET /_search
|
|
|
|
{
|
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"wkt" : "BBOX (-74.1, -71.12, 40.73, 40.01)"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
|
|
|
// CONSOLE
|
|
|
|
|
2013-08-28 19:24:34 -04:00
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
===== Geohash
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : "dr5r9ydj2y73",
|
|
|
|
"bottom_right" : "drj7teegpus6"
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
2016-05-12 06:58:22 -04:00
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2018-05-24 14:46:15 -04:00
|
|
|
|
|
|
|
When geohashes are used to specify the bounding the edges of the
|
|
|
|
bounding box, the geohashes are treated as rectangles. The bounding
|
|
|
|
box is defined in such a way that its top left corresponds to the top
|
|
|
|
left corner of the geohash specified in the `top_left` parameter and
|
|
|
|
its bottom right is defined as the bottom right of the geohash
|
|
|
|
specified in the `bottom_right` parameter.
|
|
|
|
|
|
|
|
In order to specify a bounding box that would match entire area of a
|
|
|
|
geohash the geohash can be specified in both `top_left` and
|
|
|
|
`bottom_right` parameters:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
GET /_search
|
|
|
|
{
|
|
|
|
"query": {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : "dr",
|
|
|
|
"bottom_right" : "dr"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
|
|
|
// CONSOLE
|
|
|
|
|
|
|
|
In this example, the geohash `dr` will produce the bounding box
|
|
|
|
query with the top left corner at `45.0,-78.75` and the bottom right
|
|
|
|
corner at `39.375,-67.5`.
|
|
|
|
|
2013-12-18 23:52:33 -05:00
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Vertices
|
2013-12-18 23:52:33 -05:00
|
|
|
|
|
|
|
The vertices of the bounding box can either be set by `top_left` and
|
|
|
|
`bottom_right` or by `top_right` and `bottom_left` parameters. More
|
|
|
|
over the names `topLeft`, `bottomRight`, `topRight` and `bottomLeft`
|
|
|
|
are supported. Instead of setting the values pairwise, one can use
|
|
|
|
the simple names `top`, `left`, `bottom` and `right` to set the
|
|
|
|
values separately.
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-12-18 23:52:33 -05:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top" : 40.73,
|
|
|
|
"left" : -74.1,
|
|
|
|
"bottom" : 40.01,
|
|
|
|
"right" : -71.12
|
|
|
|
}
|
2013-12-18 23:52:33 -05:00
|
|
|
}
|
2016-05-12 06:58:22 -04:00
|
|
|
}
|
2013-12-18 23:52:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-12-18 23:52:33 -05:00
|
|
|
|
|
|
|
|
2013-08-28 19:24:34 -04:00
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== geo_point Type
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
The filter *requires* the `geo_point` type to be set on the relevant
|
|
|
|
field.
|
|
|
|
|
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Multi Location Per Document
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
The filter can work with multiple locations / points per document. Once
|
|
|
|
a single location / point matches the filter, the document will be
|
|
|
|
included in the filter
|
|
|
|
|
|
|
|
[float]
|
2015-08-18 06:20:00 -04:00
|
|
|
[[geo-bbox-type]]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Type
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
The type of the bounding box execution by default is set to `memory`,
|
|
|
|
which means in memory checks if the doc falls within the bounding box
|
|
|
|
range. In some cases, an `indexed` option will perform faster (but note
|
|
|
|
that the `geo_point` type must have lat and lon indexed in this case).
|
|
|
|
Note, when using the indexed option, multi locations per document field
|
|
|
|
are not supported. Here is an example:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"bool" : {
|
|
|
|
"must" : {
|
|
|
|
"match_all" : {}
|
|
|
|
},
|
|
|
|
"filter" : {
|
|
|
|
"geo_bounding_box" : {
|
|
|
|
"pin.location" : {
|
|
|
|
"top_left" : {
|
|
|
|
"lat" : 40.73,
|
|
|
|
"lon" : -74.1
|
|
|
|
},
|
|
|
|
"bottom_right" : {
|
|
|
|
"lat" : 40.10,
|
|
|
|
"lon" : -71.12
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
},
|
2016-05-24 05:58:43 -04:00
|
|
|
"type" : "indexed"
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2016-04-14 06:38:48 -04:00
|
|
|
[float]
|
|
|
|
==== Ignore Unmapped
|
|
|
|
|
|
|
|
When set to `true` the `ignore_unmapped` option will ignore an unmapped field
|
|
|
|
and will not match any documents for this query. This can be useful when
|
|
|
|
querying multiple indexes which might have different mappings. When set to
|
|
|
|
`false` (the default value) the query will throw an exception if the field
|
|
|
|
is not mapped.
|
2018-05-14 15:54:42 -04:00
|
|
|
|
|
|
|
[float]
|
|
|
|
==== Notes on Precision
|
|
|
|
|
|
|
|
Geopoints have limited precision and are always rounded down during index time.
|
|
|
|
During the query time, upper boundaries of the bounding boxes are rounded down,
|
|
|
|
while lower boundaries are rounded up. As a result, the points along on the
|
|
|
|
lower bounds (bottom and left edges of the bounding box) might not make it into
|
|
|
|
the bounding box due to the rounding error. At the same time points alongside
|
|
|
|
the upper bounds (top and right edges) might be selected by the query even if
|
|
|
|
they are located slightly outside the edge. The rounding error should be less
|
|
|
|
than 4.20e-8 degrees on the latitude and less than 8.39e-8 degrees on the
|
|
|
|
longitude, which translates to less than 1cm error even at the equator.
|