369 lines
8.7 KiB
Plaintext
369 lines
8.7 KiB
Plaintext
[[query-dsl-geo-bounding-box-query]]
|
|
=== Geo-bounding box query
|
|
++++
|
|
<titleabbrev>Geo-bounding box</titleabbrev>
|
|
++++
|
|
|
|
A query allowing to filter hits based on a point location using a
|
|
bounding box. Assuming the following indexed document:
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
PUT /my_locations
|
|
{
|
|
"mappings": {
|
|
"properties": {
|
|
"pin": {
|
|
"properties": {
|
|
"location": {
|
|
"type": "geo_point"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PUT /my_locations/_doc/1
|
|
{
|
|
"pin": {
|
|
"location": {
|
|
"lat": 40.12,
|
|
"lon": -71.34
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TESTSETUP
|
|
|
|
Then the following simple query can be executed with a
|
|
`geo_bounding_box` filter:
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
[discrete]
|
|
==== Query Options
|
|
|
|
[cols="<,<",options="header",]
|
|
|=======================================================================
|
|
|Option |Description
|
|
|`_name` |Optional name field to identify the filter
|
|
|
|
|`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`).
|
|
|
|
|`type` |Set to one of `indexed` or `memory` to defines whether this filter will
|
|
be executed in memory or indexed. See <<geo-bbox-type,Type>> below for further details
|
|
Default is `memory`.
|
|
|=======================================================================
|
|
|
|
[[query-dsl-geo-bounding-box-query-accepted-formats]]
|
|
[discrete]
|
|
==== Accepted Formats
|
|
|
|
In much the same way the geo_point type can accept different
|
|
representations of the geo point, the filter can accept it as well:
|
|
|
|
[discrete]
|
|
===== Lat Lon As Properties
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
[discrete]
|
|
===== Lat Lon As Array
|
|
|
|
Format in `[lon, lat]`, note, the order of lon/lat here in order to
|
|
conform with http://geojson.org/[GeoJSON].
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must": {
|
|
"match_all": {}
|
|
},
|
|
"filter": {
|
|
"geo_bounding_box": {
|
|
"pin.location": {
|
|
"top_left": [ -74.1, 40.73 ],
|
|
"bottom_right": [ -71.12, 40.01 ]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
[discrete]
|
|
===== Lat Lon As String
|
|
|
|
Format in `lat,lon`.
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must": {
|
|
"match_all": {}
|
|
},
|
|
"filter": {
|
|
"geo_bounding_box": {
|
|
"pin.location": {
|
|
"top_left": "40.73, -74.1",
|
|
"bottom_right": "40.01, -71.12"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
[discrete]
|
|
===== Bounding Box as Well-Known Text (WKT)
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must": {
|
|
"match_all": {}
|
|
},
|
|
"filter": {
|
|
"geo_bounding_box": {
|
|
"pin.location": {
|
|
"wkt": "BBOX (-74.1, -71.12, 40.73, 40.01)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
[discrete]
|
|
===== Geohash
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must": {
|
|
"match_all": {}
|
|
},
|
|
"filter": {
|
|
"geo_bounding_box": {
|
|
"pin.location": {
|
|
"top_left": "dr5r9ydj2y73",
|
|
"bottom_right": "drj7teegpus6"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
|
|
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,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"query": {
|
|
"geo_bounding_box": {
|
|
"pin.location": {
|
|
"top_left": "dr",
|
|
"bottom_right": "dr"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
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`.
|
|
|
|
[discrete]
|
|
==== Vertices
|
|
|
|
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,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must": {
|
|
"match_all": {}
|
|
},
|
|
"filter": {
|
|
"geo_bounding_box": {
|
|
"pin.location": {
|
|
"top": 40.73,
|
|
"left": -74.1,
|
|
"bottom": 40.01,
|
|
"right": -71.12
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
|
|
[discrete]
|
|
==== geo_point Type
|
|
|
|
The filter *requires* the `geo_point` type to be set on the relevant
|
|
field.
|
|
|
|
[discrete]
|
|
==== Multi Location Per Document
|
|
|
|
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
|
|
|
|
[discrete]
|
|
[[geo-bbox-type]]
|
|
==== Type
|
|
|
|
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,console]
|
|
--------------------------------------------------
|
|
GET my_locations/_search
|
|
{
|
|
"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
|
|
}
|
|
},
|
|
"type": "indexed"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
|
|
[discrete]
|
|
==== 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.
|
|
|
|
[discrete]
|
|
==== 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.
|