geo-bounding-box-query.asciidoc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. [[query-dsl-geo-bounding-box-query]]
  2. === Geo Bounding Box Query
  3. A query allowing to filter hits based on a point location using a
  4. bounding box. Assuming the following indexed document:
  5. [source,js]
  6. --------------------------------------------------
  7. PUT /my_locations
  8. {
  9. "mappings": {
  10. "_doc": {
  11. "properties": {
  12. "pin": {
  13. "properties": {
  14. "location": {
  15. "type": "geo_point"
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }
  23. PUT /my_locations/_doc/1
  24. {
  25. "pin" : {
  26. "location" : {
  27. "lat" : 40.12,
  28. "lon" : -71.34
  29. }
  30. }
  31. }
  32. --------------------------------------------------
  33. // CONSOLE
  34. // TESTSETUP
  35. Then the following simple query can be executed with a
  36. `geo_bounding_box` filter:
  37. [source,js]
  38. --------------------------------------------------
  39. GET /_search
  40. {
  41. "query": {
  42. "bool" : {
  43. "must" : {
  44. "match_all" : {}
  45. },
  46. "filter" : {
  47. "geo_bounding_box" : {
  48. "pin.location" : {
  49. "top_left" : {
  50. "lat" : 40.73,
  51. "lon" : -74.1
  52. },
  53. "bottom_right" : {
  54. "lat" : 40.01,
  55. "lon" : -71.12
  56. }
  57. }
  58. }
  59. }
  60. }
  61. }
  62. }
  63. --------------------------------------------------
  64. // CONSOLE
  65. [float]
  66. ==== Query Options
  67. [cols="<,<",options="header",]
  68. |=======================================================================
  69. |Option |Description
  70. |`_name` |Optional name field to identify the filter
  71. |`validation_method` |Set to `IGNORE_MALFORMED` to
  72. accept geo points with invalid latitude or longitude, set to
  73. `COERCE` to also try to infer correct latitude or longitude. (default is `STRICT`).
  74. |`type` |Set to one of `indexed` or `memory` to defines whether this filter will
  75. be executed in memory or indexed. See <<geo-bbox-type,Type>> below for further details
  76. Default is `memory`.
  77. |=======================================================================
  78. [float]
  79. ==== Accepted Formats
  80. In much the same way the geo_point type can accept different
  81. representations of the geo point, the filter can accept it as well:
  82. [float]
  83. ===== Lat Lon As Properties
  84. [source,js]
  85. --------------------------------------------------
  86. GET /_search
  87. {
  88. "query": {
  89. "bool" : {
  90. "must" : {
  91. "match_all" : {}
  92. },
  93. "filter" : {
  94. "geo_bounding_box" : {
  95. "pin.location" : {
  96. "top_left" : {
  97. "lat" : 40.73,
  98. "lon" : -74.1
  99. },
  100. "bottom_right" : {
  101. "lat" : 40.01,
  102. "lon" : -71.12
  103. }
  104. }
  105. }
  106. }
  107. }
  108. }
  109. }
  110. --------------------------------------------------
  111. // CONSOLE
  112. [float]
  113. ===== Lat Lon As Array
  114. Format in `[lon, lat]`, note, the order of lon/lat here in order to
  115. conform with http://geojson.org/[GeoJSON].
  116. [source,js]
  117. --------------------------------------------------
  118. GET /_search
  119. {
  120. "query": {
  121. "bool" : {
  122. "must" : {
  123. "match_all" : {}
  124. },
  125. "filter" : {
  126. "geo_bounding_box" : {
  127. "pin.location" : {
  128. "top_left" : [-74.1, 40.73],
  129. "bottom_right" : [-71.12, 40.01]
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }
  136. --------------------------------------------------
  137. // CONSOLE
  138. [float]
  139. ===== Lat Lon As String
  140. Format in `lat,lon`.
  141. [source,js]
  142. --------------------------------------------------
  143. GET /_search
  144. {
  145. "query": {
  146. "bool" : {
  147. "must" : {
  148. "match_all" : {}
  149. },
  150. "filter" : {
  151. "geo_bounding_box" : {
  152. "pin.location" : {
  153. "top_left" : "40.73, -74.1",
  154. "bottom_right" : "40.01, -71.12"
  155. }
  156. }
  157. }
  158. }
  159. }
  160. }
  161. --------------------------------------------------
  162. // CONSOLE
  163. [float]
  164. ===== Bounding Box as Well-Known Text (WKT)
  165. [source,js]
  166. --------------------------------------------------
  167. GET /_search
  168. {
  169. "query": {
  170. "bool" : {
  171. "must" : {
  172. "match_all" : {}
  173. },
  174. "filter" : {
  175. "geo_bounding_box" : {
  176. "pin.location" : {
  177. "wkt" : "BBOX (-74.1, -71.12, 40.73, 40.01)"
  178. }
  179. }
  180. }
  181. }
  182. }
  183. }
  184. --------------------------------------------------
  185. // CONSOLE
  186. [float]
  187. ===== Geohash
  188. [source,js]
  189. --------------------------------------------------
  190. GET /_search
  191. {
  192. "query": {
  193. "bool" : {
  194. "must" : {
  195. "match_all" : {}
  196. },
  197. "filter" : {
  198. "geo_bounding_box" : {
  199. "pin.location" : {
  200. "top_left" : "dr5r9ydj2y73",
  201. "bottom_right" : "drj7teegpus6"
  202. }
  203. }
  204. }
  205. }
  206. }
  207. }
  208. --------------------------------------------------
  209. // CONSOLE
  210. When geohashes are used to specify the bounding the edges of the
  211. bounding box, the geohashes are treated as rectangles. The bounding
  212. box is defined in such a way that its top left corresponds to the top
  213. left corner of the geohash specified in the `top_left` parameter and
  214. its bottom right is defined as the bottom right of the geohash
  215. specified in the `bottom_right` parameter.
  216. In order to specify a bounding box that would match entire area of a
  217. geohash the geohash can be specified in both `top_left` and
  218. `bottom_right` parameters:
  219. [source,js]
  220. --------------------------------------------------
  221. GET /_search
  222. {
  223. "query": {
  224. "geo_bounding_box" : {
  225. "pin.location" : {
  226. "top_left" : "dr",
  227. "bottom_right" : "dr"
  228. }
  229. }
  230. }
  231. }
  232. --------------------------------------------------
  233. // CONSOLE
  234. In this example, the geohash `dr` will produce the bounding box
  235. query with the top left corner at `45.0,-78.75` and the bottom right
  236. corner at `39.375,-67.5`.
  237. [float]
  238. ==== Vertices
  239. The vertices of the bounding box can either be set by `top_left` and
  240. `bottom_right` or by `top_right` and `bottom_left` parameters. More
  241. over the names `topLeft`, `bottomRight`, `topRight` and `bottomLeft`
  242. are supported. Instead of setting the values pairwise, one can use
  243. the simple names `top`, `left`, `bottom` and `right` to set the
  244. values separately.
  245. [source,js]
  246. --------------------------------------------------
  247. GET /_search
  248. {
  249. "query": {
  250. "bool" : {
  251. "must" : {
  252. "match_all" : {}
  253. },
  254. "filter" : {
  255. "geo_bounding_box" : {
  256. "pin.location" : {
  257. "top" : 40.73,
  258. "left" : -74.1,
  259. "bottom" : 40.01,
  260. "right" : -71.12
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }
  267. --------------------------------------------------
  268. // CONSOLE
  269. [float]
  270. ==== geo_point Type
  271. The filter *requires* the `geo_point` type to be set on the relevant
  272. field.
  273. [float]
  274. ==== Multi Location Per Document
  275. The filter can work with multiple locations / points per document. Once
  276. a single location / point matches the filter, the document will be
  277. included in the filter
  278. [float]
  279. [[geo-bbox-type]]
  280. ==== Type
  281. The type of the bounding box execution by default is set to `memory`,
  282. which means in memory checks if the doc falls within the bounding box
  283. range. In some cases, an `indexed` option will perform faster (but note
  284. that the `geo_point` type must have lat and lon indexed in this case).
  285. Note, when using the indexed option, multi locations per document field
  286. are not supported. Here is an example:
  287. [source,js]
  288. --------------------------------------------------
  289. GET /_search
  290. {
  291. "query": {
  292. "bool" : {
  293. "must" : {
  294. "match_all" : {}
  295. },
  296. "filter" : {
  297. "geo_bounding_box" : {
  298. "pin.location" : {
  299. "top_left" : {
  300. "lat" : 40.73,
  301. "lon" : -74.1
  302. },
  303. "bottom_right" : {
  304. "lat" : 40.10,
  305. "lon" : -71.12
  306. }
  307. },
  308. "type" : "indexed"
  309. }
  310. }
  311. }
  312. }
  313. }
  314. --------------------------------------------------
  315. // CONSOLE
  316. [float]
  317. ==== Ignore Unmapped
  318. When set to `true` the `ignore_unmapped` option will ignore an unmapped field
  319. and will not match any documents for this query. This can be useful when
  320. querying multiple indexes which might have different mappings. When set to
  321. `false` (the default value) the query will throw an exception if the field
  322. is not mapped.
  323. [float]
  324. ==== Notes on Precision
  325. Geopoints have limited precision and are always rounded down during index time.
  326. During the query time, upper boundaries of the bounding boxes are rounded down,
  327. while lower boundaries are rounded up. As a result, the points along on the
  328. lower bounds (bottom and left edges of the bounding box) might not make it into
  329. the bounding box due to the rounding error. At the same time points alongside
  330. the upper bounds (top and right edges) might be selected by the query even if
  331. they are located slightly outside the edge. The rounding error should be less
  332. than 4.20e-8 degrees on the latitude and less than 8.39e-8 degrees on the
  333. longitude, which translates to less than 1cm error even at the equator.