Does Elasticsearch support geo queries like ST_DWithin in postgis - elasticsearch

How to perform such query in Elasticsearch that whether a geo_point is within the specified distance(or radius/buffer) of a line(depicted by 2 pairs of lat/lon)
shape like this

This is not implemented in Elastic as far as I know. But you can still achieve what you want by calculating the polygon offline and then use it in a geo_polygon query. The geo_shape query could also be used but you need a geo_shape field instead of a geo_point one.
So, for instance, using turf you can precompute the polygon around the line using the buffer feature. Below, I'm defining a line along some road somewhere in San Jose (CA) and a buffer of 50 meters around that line/road:
const line = turf.lineString([[-121.862282,37.315430], [-121.851553,37.305532]], {name: 'line 1'});
const bufferPoly = turf.buffer(line, 50, {units: 'meters'});
You'll get the following polygon (abbreviated)
{
"type": "Feature",
"properties": {
"name": "line 1"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-121.85121372045873,
37.305765606399724
],
[
-121.85116304254947,
37.30570833334188
],
[
-121.85112738572346,
37.30564429665501
],
[
-121.85110812025259,
37.30557595721911
],
...
[
-121.85121372045873,
37.305765606399724
]
]
]
}
}
Which looks like this:
Then you can leverage the geo_polygon query like this:
GET /_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_polygon": {
"your_geo_point": {
"points": [
[
-121.85121372045873,
37.305765606399724
],
[
-121.85116304254947,
37.30570833334188
],
[
-121.85112738572346,
37.30564429665501
],
[
-121.85110812025259,
37.30557595721911
],
...
[
-121.85121372045873,
37.305765606399724
]
]
}
}
}
}
}
}

Related

elasticsearch: DISJOINT query relation not supported for Field

I have created the simplest index in ES v7.10:
it maps mylocation field into geo_point (not geo_shape):
PUT /myindex
{
"mappings": {
"dynamic": "false",
"properties": {
"mylocation": {
"type": "geo_point"
}
}
}
}
then I pushed some data inside. I've omitted this to shorten the question...
When I query the below, all works fine:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"mylocation": {
"shape": {
"type": "polygon",
"coordinates": [[ [ 13.0, 53.0 ], [ 0.0, 1.0 ], [ 0.0, 0.0 ], [ 13.0, 53.0 ] ]]
},
"relation": "intersects"
}
}
}
}
}
}
when I replace the intersects with disjoint, I get the error:
DISJOINT query relation not supported for Field [mylocation].
In elastic docs (for the relevant version, 7), it is mentioned that "Geoshape query filter documents indexed using the geo_shape or geo_point type" (and I am using the geo_point). Down the same page, it is written the "disjoint" is supported!
What am I missing? Why do I get the error?
No idea how I have missed it, but in v7.10 docs (link in the question) they write in the next paragraph:
When searching a field of type geo_point there is a single supported
spatial relation operator:
INTERSECTS - (default) Return all documents whose geo_point field
intersects the query geometry.
In v7.17 they do not have this limitation anymore...

Combining terms with synonyms - ElasticSearch

I am new to Elasticsearch and have a synonym analyzer in place which looks like-
{
"settings": {
"index": {
"analysis": {
"filter": {
"graph_synonyms": {
"type": "synonym_graph",
"synonyms": [
"gowns, dresses",
"backpacks, bags",
"coats, jackets"
]
}
},
"analyzer": {
"search_time_analyzer": {
"tokenizer": "standard",
"filter": [
"lowercase",
"graph_synonyms"
]
}
}
}
}
}
}
And the mapping looks like-
{
"properties": {
"category": {
"type": "text",
"search_analyzer": "search_time_analyzer",
"fields": {
"no_synonyms": {
"type": "text"
}
}
}
}
}
If I search for gowns, it gives me proper results for both gowns as well as dresses.
But the problem is if I search for red gowns, (the system does not have any red gowns) the expected behavior is to search for red dresses and return those results. But instead, it returns results of gowns and dresses irrespective of the color.
I would want to configure the system such that it considers both the terms and their respective synonyms if any and then return the results.
For reference, this is what my search query looks like-
"query":
{
"bool":
{
should:
[
{
"multi_match":
{
"boost": 300,
"query": term,
"type": "cross_fields",
"operator": "or",
"fields": ["bu.keyword^10", "bu^10", "category.keyword^8", "category^8", "category.no_synonyms^8", "brand.keyword^7", "brand^7", "colors.keyword^2", "colors^2", "size.keyword", "size", "hash.keyword^2", "hash^2", "name"]
}
}
]
}
}
Sample document:
_source: {
productId: '12345',
name: 'RUFFLE FLORAL TRIM COTTON MAXI DRESS',
brand: [ 'self-portrait' ],
mainImage: 'http://test.jpg',
description: 'Self-portrait presents this maxi dress, crafted from cotton, to offer your off-duty ensembles an elegant update. Trimmed with ruffled broderie details, this piece is an effortless showcase of modern femininity.',
status: 'active',
bu: [ 'womenswear' ],
category: [ 'dresses', 'gowns' ],
tier1: [],
tier2: [],
colors: [ 'WHITE' ],
size: [ '4', '6', '8', '10' ],
hash: [
'ballgown', 'cotton',
'effortless', 'elegant',
'floral', 'jar',
'maxi', 'modern',
'off-duty', 'ruffle',
'ruffled', '1',
'2', 'crafted'
],
styleCode: '211274856'
}
How can I achieve the desired output? Any help would be appreciated. Thanks
You can configured index time analyzer insted of search time analyzer like below:
{
"properties": {
"category": {
"type": "text",
"analyzer": "search_time_analyzer",
"fields": {
"no_synonyms": {
"type": "text"
}
}
}
}
}
Once you done with index mapping change, reindex your data and try below query:
Please note that I have changed operator to and and analyzer to standard:
{
"query": {
"multi_match": {
"boost": 300,
"query": "gowns red",
"analyzer": "standard",
"type": "cross_fields",
"operator": "and",
"fields": [
"category",
"colors"
]
}
}
}
Why your current query is not working:
Inexing:
Your current index mapping indexing data with standard analyzer so it will not index any of your category with synonyms values.
Searching:
Your current query have operator or so if you search for red gowns then it will create query like red OR gowns OR dresses and it will giving you result irrespective of the color. Also, if you change operator to and in existing configuration then it will return zero result as it will create query like red AND gowns AND dresses.
Solution: Once you done changes as i suggsted it will index synonyms for category field as well and it will work with and operator. So if you try query gowns red then it will create query like gowns AND red. It will match because category field have both values gowns and dresses due to synonyms applied at index time.

Elasticsearch point in polygon query

i'm using Elasticsearch V6.7.1.
I have created few indices and filled them with data. each index has a field
gps_coords with lat andlon` values ( coordinates )
What I want to do is to write a query, where i pass a polygon and check if a certain point falls into that polygon, is that possible ?
This is a query that I've already tried:
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "polygon",
"coordinates" : [
[25.0245351, 54.5693374],
[25.0245351, 54.83232],
[25.4815808, 54.83232],
[25.4815808, 54.5693374],
[25.0245351, 54.5693374]
]
},
"relation": "within"
}
}
}
}
}
}
But it returns this error:
{
"error": {
"root_cause": [
{
"type": "parse_exception",
"reason": "Invalid LinearRing found. Found a single coordinate when expecting a coordinate array"
}
],
"type": "parse_exception",
"reason": "Invalid LinearRing found. Found a single coordinate when expecting a coordinate array"
},
"status": 400
}
Here is my index mapping:
[
'index' => 'places',
'body' => [
'mappings' => [
'place' => [
"properties" => [
"gps_coords" => [
"ignore_malformed" => true,
"type" => "geo_shape"
]
]
],
],
"number_of_replicas" => 0
]
]
];
can someone please point me to the right direction.
Thank you !
First, in the query sample you use location field instead of gps_coords, as already stated in the comment. But I believe this is just a typo because that's not the source of the error.
The reason you receive a parse exception is that you are missing one pair of brackets in the polygon definition in geo_shape query. See the correct form here. The correct form would be (just the relevant part):
"shape": {
"type": "polygon",
"coordinates" : [
[[25.0245351, 54.5693374],
[25.0245351, 54.83232],
[25.4815808, 54.83232],
[25.4815808, 54.5693374],
[25.0245351, 54.5693374]]
]
}
Yeah, sorry, my bad, just copied the example from ES docs not my code. Okey, will try to add those brackets and see if it helps, thanks!

Issue with radius search?

We're on Elasticsearch 1.3.2.
We can't seem to get a record returned when doing a radial search against a linestring.
Our mapping can be broken down to this:
{
"simpleline":{
"properties": {
"geo_linestring": {
"type": "geo_shape",
"tree": "quadtree",
"tree_levels": 26
}
}
}
}
We have a linear path that sort of forms a "U":
{
"geo_linestring": {
"type": "linestring",
"coordinates": [
[
-96.6906661987305,
47.7989692687988
],
[
-96.7057800292969,
47.2933502197266
],
[
-96.3336181640625,
47.2952117919922
],
[
-96.3226318359375,
47.8358612060547
]
]
}
}
The connection between middle two points appear to be within 15-20 miles of the city of Felton, MN. So, if we wanted to find all "trails" within 30 miles of Felton, we want this to appear.
However, filtering on a circle centered at Felton (30 mile radius) does not return the item. Increasing the radius to 40 miles, however, does:
{
"filter": {
"geo_shape": {
"geo_linestring": {
"shape": {
"type": "circle",
"radius": "30mi",
"coordinates": [
-96.5055999755859,
47.0751991271973
]
}
}
}
}
}
Are we just misunderstanding how this search works, or is there an issue with how we're approaching this?

Can not query geo_point using geo polygon filter

Hi I'm trying to query geo_point in ElasticSearch, using the query syntax geo polygon filter in the official document], but no reusult is returned.
Here are some details:
I use river plugin to index the data from MySQL into ES with the definition of mapping (a nested structure but coordinate.value is geo_point).
I can see the documents from head plugin:
The query json is:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"geo_polygon": {
"coordinate.value": {
"points": [
[
-180,
90
],
[
-180,
-90
],
[
180,
-90
],
[
-180,
90
]
]
}
}
}
}
}
}
Can anyone tell me what's the correct query method to get geo_point? Thanks
polygon should be closed (ie first and last points should be the same).

Resources