⚡ ElasticsearchBook is crafted by Jozef Sorocin (🟢 Book a consulting hour) and powered by:
- Spatialized.io (Elasticsearch & Google Maps consulting)
- in cooperation with Garages-Near-Me.com (Effortless parking across Germany)
Use Case
I want to retrieve locations
- that are within the NYC area, defined by a rectangular viewport
- and boost those that are in Brooklyn, described by a GeoJSON polygon:
Approach
Data
Let's create an index:
PUT locations
{
"mappings": {
"properties": {
"geometry": {
"type": "object",
"properties": {
"coordinates": {
"type": "geo_point"
}
}
}
}
}
}
Notice how the
geometry.coordinates
field is explicitly declared as a geo_point
.
It's tempting to use the geo_shape
field type on the whole geometry
field because a Point
is a valid GeoJSON type (which a geo_shape
would accept) but the geo_bounding_box
query we'll be using only allows filtering on explicitly declared geo_point
fields!Next, let's add some locations into our index:
POST _bulk
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-73.78964,40.70269]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.14181,40.76044]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.18276,40.85367]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.12306,40.62101]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.0113,40.83436]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.27228,40.72379]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-73.7888,40.59183]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-73.87138,40.86417]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-73.89522,40.71144]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.12918,40.72388]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.04345,40.86526]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.27225,40.84098]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.19762,40.69674]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-73.78374,40.89914]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.23609,40.86037]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-73.94215,40.67004]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.12929,40.60387]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.08588,40.68269]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-74.27447,40.89801]}}
{"index":{"_index":"locations"}}
{"geometry":{"type":"Point","coordinates":[-77.17435,38.98741]}, "meta": "not in nyc"}
Bounding Box Recap
In order to describe an area of a map (that uses the Mercator projection) with minimum points, we'll need a rectangle's opposing corners — typically the south west and the north east:
- South West → Bottom Left → [ min(x), min(y) ]
- North East → Top Right → [ max(x), max(y) ]
Many frontend mapping libraries implement a
getBounds()
method which returns the viewport's NE & SW corners — most notably Mapbox, Google Maps, and Leaflet.As soon as we've obtained the two points, we can plug them into the
geo_bounding_box
query:POST locations/_search
{
"query": {
"geo_bounding_box": {
"geometry.coordinates": {
"bottom_left": [-74.32457, 40.51119],
"top_right": [-73.72444, 40.93012]
}
}
}
}
Alternatively, the opposing points' coordinates can be deconstructed into a bounding box: