Elastic Search Geo Spatial search implementation
Text & geo queries function separately of one another. Let's take a concrete example:
PUT restaurants{ "mappings": { "properties": { "location": { "type": "geo_point" }, "menu": { "type": "text", "fields": { "keyword": { "type": "keyword" } } } } }}POST restaurants/_doc{ "name": "rest1", "location": { "lat": 40.739812, "lon": -74.006201 }, "menu": [ "european", "french", "pizza" ]}POST restaurants/_doc{ "name": "rest2", "location": { "lat": 40.7403963, "lon": -73.9950026 }, "menu": [ "pizza", "kebab" ]}
One would then match
a text field, use a geo_distance
filter:
GET restaurants/_search{ "query": { "bool": { "must": [ { "match": { "menu": "pizza" } }, { "geo_distance": { "distance": "0.5mi", "location": { "lat": 40.7388, "lon": -73.9982 } } }, { "function_score": { "query": { "match_all": {} }, "boost_mode": "avg", "functions": [ { "gauss": { "location": { "origin": { "lat": 40.7388, "lon": -73.9982 }, "scale": "0.5mi" } } } ] } } ] } }}
Since the geo_distance
query only assigns a true/false value (--> score=1; only checking if the location is within a given radius), one may want to apply a gauss function_score
to boost the locations closer to a given origin.
Finally, these scores are overridable by using a _geo_distance
sort whereby you'd order by the proximity only (while of course keeping the match
query intact):
... "query: {...}, "sort": [ { "_geo_distance": { "location": { "lat": 40.7388, "lon": -73.9982 }, "order": "asc" } } ]}