Elasticsearch geosearch with distance preference - elasticsearch

Sorry for the noob question... I have Restaurant objects in Elasticsearch 2.3, each has a GeoPoint and a home delivery distance preference. In pseudocode
restaurant: {
location: (x, y)
deliveryPreference: 10km
}
and a user:
user {
location: (a,b)
}
How would I issue a search for a user looking for all restaurants that can deliver in his area?

The solution involves using geo_shapes. You need to model the restaurant documents as follows:
PUT restaurants
{
"mappings": {
"restaurant": {
"properties": {
"name": {
"type": "text"
},
"location": {
"type": "geo_point"
},
"delivery_area": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "1m"
}
}
}
}
}
You can then index your restaurants as follows:
POST /restaurants/restaurant/1
{
"name": "My Food place",
"location": [-45.0, 45.0], <-- lon, lat !!!
"delivery_area": {
"type": "circle",
"coordinates" : [-45.0, 45.0], <-- lon, lat !!!
"radius" : "10km"
}
}
Each restaurant will thus be associated with a circle shape centered on its location and with a proper radius.
Finally, when a user wants to know which restaurant can deliver at the location she is currently at, you can issue the following geo_shape query:
POST /restaurants/_search
{
"query":{
"bool": {
"filter": {
"geo_shape": {
"delivery_area": {
"shape": {
"type": "point",
"coordinates" : [<user_lon>, <user_lat>]
},
"relation": "contains"
}
}
}
}
}
}
In this query, we are retrieving restaurants whose delivery_area shape contains the point the user is currently located at.

Index the restraunts documents with following mappings
{
"mappings": {
"type_name": {
"properties": {
"name": {
"type": "text"
},
"location": {
"type": "text"
},
"location_geo": {
"type": "geo_point"
}
}
}
}
}
Use geo_filter query
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": "10km",
"location_geo": {
"lat": 40,
"lon": -70
}
}
}
}
}
}

Related

what is the best way to find available points(merchants) around a point(user) if these points(merchants) use different radius in Elasticsearch

I used geo_shape for this problem, want to know if there are some other better ways(faster) to solve this problem, ES version is 6.5.
mapping:
{
"index": {
"mappings": {
"merchant": {
"_all": {
"enabled": false
},
"properties": {
"delivery_circle": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "50.0m",
"distance_error_pct": 0.025
}
}
}
}
}
}
document example:
{
"_source": {
"id": 1,
"delivery_circle": {
"coordinates": [ // merchant location, its radius is 4km
123.456,
1.2345
],
"radius": "4000m",
"type": "circle"
}
}
}
{
"_source": {
"id": 2,
"delivery_circle": {
"coordinates": [ // merchant location, its radius is 5km
123.567,
1.3456
],
"radius": "5000m",
"type": "circle"
}
}
}
search query example:
{
"query": {
"bool": {
"filter": [
{
"geo_shape": {
"delivery_circle": {
"relation": "contains",
"shape": {
"coordinates": [ // user location
123,
1
],
"type": "point"
}
}
}
}
]
}
}
}
This is off topic suggestion, but you can consider using geohash for the same. This can reduce your search time complexity.
https://en.wikipedia.org/wiki/Geohash

Find coordinates in a polygon

How can I find polygons that stored in elastic index.
Simple mapping:
PUT /regions
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
And simple polygon:
/regions/_doc/1
{
"location" : {
"type" : "polygon",
"coordinates" : [
[
[53.847332102970626,27.485155519098047],
[53.84626875748117,27.487134989351038],
[53.8449047241684,27.48501067981124],
[53.84612634308789,27.482945378869765],
[53.847411219859,27.48502677306532],
[53.847332102970626,27.485155519098047]
]
]
}
}
According to documentation I can only search coordinates within polygon only if the polygon is contained in the request Geo-polygon query, but I need to find polygons by coordinates in query. Elasticsearch 7.6 version.
Query:
{
"query": {
"match_all": {}
},
"filter": {
"geo_shape": {
"geometry": {
"shape": {
"coordinates": [
53.846415,
27.485756
],
"type": "point"
},
"relation": "whithin"
}
}
}
}
You were on the right path but your query was heavily malformed. Here's the fix:
{
"query": {
"bool": {
"filter": {
"geo_shape": {
"location": {
"shape": {
"coordinates": [
53.846415,
27.485756
],
"type": "point"
},
"relation": "intersects"
}
}
}
}
}
}
Notice how I used intersects instead of within. The reason is explained in this GIS StackExchange answer.

Elastic Search Geo Spatial search implementation

I am trying to understand how elastic search supports Geo Spatial search internally.
For the basic search, it uses the inverted index; but how does it combine with the additional search criteria like searching for a particular text within a certain radius.
I would like to understand the internals of how the index would be stored and queried to support these queries
Text & geo queries are executed 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"
]
}
You'd then match a text field and apply 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 boolean value (--> score=1; only checking if the location is within a given radius), you may want to apply a gaussian function_score to boost the locations that are closer to a given origin.
Finally, these scores are overridable by using a _geo_distance sort where you'd order by the proximity (while of course keeping the match query intact):
...
"query: {...},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 40.7388,
"lon": -73.9982
},
"order": "asc"
}
}
]
}

Elasticsearch geo_shape query giving wrong results

I am facing am issue, I know how to find all geo_points in a particular radius but I need to find how many regions or geo_shape a particular point lies in. To solve this issue, I have made following index:
PUT /users
And this mapping:
PUT /users/_mapping/_doc
{
"properties": {
"radius": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "100m"
},
"point":{
"type":"geo_point"
}
}
}
Also following is the sample document:
POST /users/_doc
{
"radius":{
"type" : "circle",
"coordinates" : [28.363157, 77.287550],
"radius" : "100km"
},
"point":{
"lat" : 28.363157,
"lon": 77.287550
}
}
The query I am making is:
POST /users/_search
{
"query":{
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"radius": {
"shape": {
"type": "point",
"coordinates" : [29.363157, 77.28755]
},
"relation": "contains"
}
}
}
}
}
}
Now, the distance between the latlongs in query and doc is almost 110-112kms, hence above query returns exact result, but when I query [30.363157, 77.28755], it still returns the document even when the distance is over 220kms.
What am I doing wrong?

Elasticsearch - find points inside huge geo shape

I have 'shapes' index that stores a lot of huge geoshapes (original shapefile for one geoshape was 6MB in size).
I'm using this mapping:
"shape": {
"type": "geo_shape",
"tree": "quadtree",
"tree_levels": "20"
},
"_all": {
"enabled": false
},
"dynamic": "true"
I also have 'photos' index. Each photo have latitude and longitude presented as geoshape with type Point.
e.g.
"location": {
"type": "Point",
"coordinates": [
-103.262600,
43.685315
]
}
Mapping for it:
"location": {
"type": "geo_shape",
"tree": "quadtree",
"tree_levels": 20
}
I'm trying to find all photos that located inside selected shape by using following query:
GET photos/_search
{
"query": {
"filtered": {
"filter": {
"geo_shape": {
"location": {
"relation": "intersects",
"indexed_shape": {
"id": "huge_region_shape_id",
"type": "country",
"index": "shapes",
"path": "shape"
}
}
}
},
"query": {
"match_all": {}
}
}
}
}
Issues:
1) On a huge shapes this query executes several minutes or forever.
2) Just searching shapes by some parameters takes a lot of time if "shape" included into source, but if I exclude it - geo_shape filter will throw an exception - "Shape found but missing field"
In mapping:
_source: {
excludes : ['shape']
}
Is there some way to solve this issues?

Resources