Elasticsearch geo_distance filter - distance unit set to km but seems to calculate with meters - elasticsearch

I'm using geo_distance filter to get the points that are within a certain distance to a reference point. As a distance_unit I set km, however, when I'm running my code I'm pretty sure that Elastic calculates meters, and not kilometers (so in this particular case below I get the points that are within 20 meters, not 20 kilometers).
Any ideas why is it using meters rather than kilometers?
{
"query": {
"filtered": {
"query": {
"bool": {
"must_not": [
{
"term": {
"_id": {
"value": idnum
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": 20,
"distance_unit": "km",
"geopoint": {
"lat": lat,
"lon": lng
}
}
}
}
}
}

use "distance": "20KM", rather than distance_unit....

Related

Elasticsearch geo distance query exclude water bodies

I am working on Elasticsearch and I have a use case where I have to list apartments within 20 miles from me.
Here is the query I am using:
{
"query": {
"bool": {
"filter": [
{
"geo_distance": {
"distance": "20mi",
"distance_type": "plane",
"location": {
"lon": -122.4194,
"lat": 37.7749
}
}
}
]
}
}
}
But this query does not exclude water bodies and other inaccessible geography. Does elasticsearch exclude them under the query or is there a specific way to do it?

geo_distance doesn't return any hit Elasticsearch

Have a problem with this query, when I use geo_distance filter, nothing returned from query. When I remove it I get proper results. Query is bellow:
GET _search
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": 20,
"distance_unit": "km",
"coordinates": [48.8488576, 2.3354223]
}
},
"must": {
"term": {
"_type": {
"value": "staff"
}
}
},
"must_not": [
{
"term": {
"cabinet.zipcode": {
"value": "75006"
}
}
},
{
"term": {
"next_availability_in_days": {
"value": "-1"
}
}
}
]
}
}
}
I would appreciate if someone gives me a hint.
UPDATE
When I run Elasticsearch Ruby DSL with same query logic, I get proper results:
<Elasticsearch::Model::Searching::SearchRequest:0x007ff335763560
#definition=
{:index=>["development_app_scoped_index_20170428134744",
"development_app_scoped_index_20170428134744"], :type=>["staff", "light_staff"],
:body=>
{:query=>
{:bool=>
{:must_not=>[
{:term=>{"cabinet.zipcode"=>75006}},
{:term=> {:next_availability_in_days=>-1}}
],
:must=>[
{:term=>{:_type=>"staff"}}
],
:filter=>{:geo_distance=>
{:coordinates=>
{:lat=>48.8488576, :lon=>2.3354223},
:distance=>"6km"
}
}}},
:sort=>[
{:type=>{:order=>"desc"}},
{"_geo_distance"=>{"coordinates"=>"48.8488576,2.3354223", "order"=>"asc",
"unit"=>"km"}},
{:next_availability_in_days=>{:order=>"asc"}},
{:priority=>{:order=>"asc"}}
]
}}
So this is really weird and I'm not sure what's going wrong in ES syntax, but it definitely should work as expected.
Thanks.
There is probably nothing in the range that you have entered.
Try to increase the "distance": 20 field to "distance": 500 and check the results then. For example the distance between these two geo points [0,0] and [0,1] is ~138.3414KM .
Another suggestion is to get rid of the "distance_unit" field and put the
and put the KM inside the "distance" field as following:
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": "20km",
"coordinates": [
48.8488576,
2.3354223
]
}
}
}
}
}

Elasticsearch apply condintions in query on basis of results count

Is there any way in Elasticsearch for following type of outcome
"Apply first condition, if no results found then apply next conditions and so on.."
I am aware of basics of ES queries. I know this can be done by querying again and again on results basis but I want to do this in single query for the sake of time and efficiency.
Here is my current query
GET_search{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 28.6143519,
"lon": -81.50773
},
"bottom_right": {
"lat": 28.3479859,
"lon": -81.22977
}
}
}
}
]
}
}
}
},
"size": 10,
"from": 0,
"sort": {
"search_score": {
"order": "desc"
}
}
}
Now what I want to do is, if this query hits zero results then this should search for another increased set of lat lon bounds. I can do this by requering elasticsearch but it will be an inefficient way.
I want to know if is this possible in elasticsearch?

With Elasticsearch function score query with decay against a geo-point, is it possible to set a target distance?

It doesn't seem possible based on https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html , but I'd like confirmation.
In plain English, I'm asking to score the results (with geo-point locations) by how close they are to 500km from some latitude, longitude origin.
It's confusing because there is a parameter called "offset" but according to the documentation it doesn't seem to be an offset from origin (eg. distance) but instead seems to mean "threshold" instead.
I see a few ways to accomplish this:
A. One way would be to simply sort by distance in reverse order from the origin. You'd use a geo_distance query and then sort by distance. In the following query, the most distant documents will come up first, i.e. the sort value is the distance from the origin and we're sorting in decreasing order.
{
"query": {
"filtered": {
"filter": {
"geo_distance": {
"from" : "100km",
"to" : "200km",
"location": {
"lat": 10,
"lon": 20
}
}
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 10,
"lon": 20
},
"order": "desc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
B. The second way involves using a geo_distance_range query in order to define a "ring" around the origin. The width of that ring could somehow symbolize the offset + scale you'd use in a gauss function (although there would be no decay). Here we define a ring that is 10km wide at 500km distance from the origin point and sort the documents by distance in that ring.
{
"query": {
"filtered": {
"filter": {
"geo_distance_range": {
"from": "495km",
"to": "505km",
"location": {
"lat": 10,
"lon": 20
}
}
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 10,
"lon": 20
},
"order": "desc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
C. The last way is a bit more involved. We're basically after an "inverse gauss" shape, basically this figure (33), but upside-down, or this one which better represents the donut shape we're after. We can combine solution B above with a gauss function that would only score within that ring. In the query below, we're basically saying that we're only interested in the locations around 500km from the origin and we let a gauss function kick in only for those documents. It's not perfect, though, but might be close enough to what you need.
{
"query": {
"filtered": {
"filter": {
"geo_distance_range": {
"from": "495km",
"to": "505km",
"location": {
"lat": 10,
"lon": 20
}
}
},
"query": {
"function_score": {
"functions": [
{
"gauss": {
"location": {
"origin": {
"lat": 10,
"lon": 20
},
"offset": "500km",
"scale": "5km"
}
}
}
]
}
}
}
},
"sort": {
"_score": "desc"
}
}

Array of locations in elasticserach spatial query

I am new to this elastic search concept i can't find a solution for my problem. suppose consider the following query.
GET banknew/_search/
{
"query": {
"match_all": {}
},
"filter": {
"geo_distance": {
"location": {
"lat": 8.722479,
"lon": 78.13047
},
"distance": "5km"
}
}
}
This will gave me the result. The above query is for 1 location(means 1 lat, lng). But i have to get the result for multiple locations(means for 2 or more lat, lng). What i tried is
GET banknew/_search/
{
"query": {
"match_all": {}
},
"filter": {
"geo_distance": {
"location": [{
"lat": 8.722479,
"lon": 78.13047
},{
"lat": 8.722479,
"lon": 78.13047
} ],
"distance": "5km"
}
}
}
I have to get the result of points within 5km for 1st location and also 2nd location.
But i am receiving error `"error": "SearchPhaseExecutionException[Failed to execute phase [query], all shards failed". Whether its possible. Please guide me. Thanks in advance
You could use another geo_distance filter and wrap it up in a bool filter.
If you are searching result at 5km from first location OR second location, add it in the should clause.
Try something like this :
GET banknew/_search/
{
"query": {
"match_all": {}
},
"filter": {
"bool": {
"should": [
{
"geo_distance": {
"distance": "5km",
"location": {
"lat": lat1,
"lon": lon1
}
}
},
{
"geo_distance": {
"distance": "5km",
"location": {
"lat": lat2,
"lon": lon2
}
}
}
],
"minimum_should_match": 1
}
}
}

Resources