Geo distance query with regex query in elastic search - elasticsearch

I want to make a query with a keyword and show only the posts 150km around me within the queried keyword my query below is working but shows all the posts
{
"query": {
"regexp": {
"title": {
"value": ".*h.*",
"flags": "ALL",
"max_determinized_states": 10000,
"rewrite": "constant_score"
}
}
},
"sort": [{
"date": {
"order": "desc"
}
}]
}
but when I add the filter query like follows I am receiving parsing error
"filter": {
"geo_distance": {
"distance": "150km",
"location": {
"lat": \(latitude),
"lon": \(longitude)
}
}
}
Any one can help please

Here is the query you should be using, which combines both the regexp query and the geo_distance query using a bool/filter query:
{
"query": {
"bool": {
"filter": [
{
"geo_distance": {
"distance": "150km",
"location": {
"lat": \(latitude),
"lon": \(longitude)
}
}
},
{
"regexp": {
"title": {
"value": ".*h.*",
"flags": "ALL",
"max_determinized_states": 10000,
"rewrite": "constant_score"
}
}
}
]
}
},
"sort": [
{
"date": {
"order": "desc"
}
}
]
}

Related

Is there a way to return the geo distance when NOT sorting with _geo_distance?

I need to return the computing distance in the result for the geo location.but not using the sort
currently I'm using sorting but it ignores the exist field
here is my query:
"query": {
"bool": {
"filter": [
{
"match": {
"field 1": "value"
}
},
{
"match": {
"field2": "A"
}
},
{
"geo_distance": {
"distance": "20km",
"location": "34,-2.99"
}
}
], "should": [
{
"exists": {
"field": "field3",
"boost": 10000
}
}
]
}
},
"size": 500,
"sort": [
{
"_geo_distance": {
"location": {
"lat": 34,
"lon": 2.99
},
"order": "asc",
"unit": "km",
"mode": "min",
"distance_type": "arc",
"ignore_unmapped": "true"
}
}
]
I need if the field3 exist it gets higher ranking
If I understand your problem correctly. This query should work:
"query": {
"bool": {
"filter": [
{
"match": {
"field 1": "value"
}
},
{
"match": {
"field2": "A"
}
},
{
"geo_distance": {
"distance": "20km",
"location": "34,-2.99"
}
}
]
}
},
"size": 500,
"sort": [
{
"_script": {
"type": "number",
"script": {
"source": "doc['field3'].size() > 0 ? 10000 : 0"
},
"order": "asc"
}
},
{
"_geo_distance": {
"location": {
"lat": 34,
"lon": 2.99
},
"order": "asc",
"unit": "km",
"mode": "min",
"distance_type": "arc",
"ignore_unmapped": "true"
}
}
]
I am checking if field exist and boosting it's score

Elasticsearch scoring documents liked by similar users higher

In Elasticsearch I have two indexes, places and users. This is the mapping for places:
mappings: {
location: {
type: "geo_point"
}
}
And this is the mapping for users:
mappings: {
likes: {
type: "keyword"
},
seen: {
type: "keyword"
}
}
As you can see a user can like and see different places. Now I want to query places which a user has not seen or liked yet and want to show places which are liked by users who like similar places as the querying user first. This is the query I was able to come up with:
POST /places/_search
{
"_source": [
"id"
],
"size": 1,
"query": {
"function_score": {
"query": {
"bool": {
"must_not": [
{
"terms": {
"_id": {
"index": "users",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "seen"
}
}
},
{
"terms": {
"_id": {
"index": "users",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "likes"
}
}
}
],
"filter": {
"geo_distance": {
"distance": "200km",
"location": {
"lat": 52,
"lon": 13
}
}
}
}
},
"random_score": {},
"boost_mode": "replace"
}
}
}
However, at this moment this query just assigns a random score to all results. As I'm new to Elasticsearch I'm struggling to come up with a scoring function to achieve scoring places, that similar users have liked, higher, especially because the data about user likes is stored in a different index than the one I'm actually querying. What would be the best approach this problem? Is something like this even possible with my current data model?
I think you have to perform two request like below
Get all the similar user's likes location ids
Then use the location ids to match and exclude the likes and seen location
Step 1 query example :
GET users/_search
{
"_source": [
"likes"
],
"query": {
"bool": {
"filter": [
{
"terms": {
"likes": {
"index": "users",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "likes"
}
}
}
],
"must_not": [
{
"ids": {
"values": [
vu0E1rjJEqcgyfj29fwZ
]
}
}
]
}
}
}
Step 2 query example :
GET places/_search
{
"_source": [
"id"
],
"size": 1,
"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"ids": {
"values": [] # Put all the similar user like ids here
}
}
],
"must_not": [
{
"terms": {
"_id": {
"index": "users",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "seen"
}
}
},
{
"terms": {
"_id": {
"index": "users",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "likes"
}
}
}
],
"filter": {
"geo_distance": {
"distance": "200km",
"location": {
"lat": 52,
"lon": 13
}
}
}
}
},
"random_score": {},
"boost_mode": "replace"
}
}
}
You could use a gauss decay function from within your function score query, as nicely described here:
GET /places/_search
{
"size": 5,
"query": {
"function_score": {
"query": {
"bool": {
"must_not": [
{
"terms": {
"_id": {
"index": "users",
"type": "_doc",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "seen"
}
}
},
{
"terms": {
"_id": {
"index": "users",
"type": "_doc",
"id": "vu0E1rjJEqcgyfj29fwZ",
"path": "likes"
}
}
}
]
}
},
"functions": [
{
"gauss": {
"location": {
"origin": {
"lat": 52,
"lon": 13
},
"scale": "200km"
}
}
}
],
"boost_mode": "replace"
}
}
}
But I wonder what the current connection between the likes and places is in your data model.

Elastic Search doesn't respect size when using aggregations

I am new to Elastic Search so please forgive me if the answer is obvious.
I have modified a query to use aggs to show 'distinct' results. However, after adding the aggs the size doesn't seem to work anymore - it always returns 10 results no matter what I set size to.
Would anyone know how I could use both aggs and size together?
My query is:
{
"size": "15",
"from": "0",
"query": {
"bool": {
"filter": [
{
"term": {
"category": "Cars"
}
},
{
"term": {
"location": "Sydney"
}
},
{
"term": {
"status": true
}
}
]
}
},
"sort": [
{
"_score": "desc"
},
{
"brand": "asc"
}
],
"aggs": {
"brand": {
"terms": {
"field": "brand",
"order": {
"price": "asc"
}
},
"aggs": {
"brand": {
"top_hits": {
"size": 1,
"sort": [
{
"price": {
"order": "asc"
}
}
]
}
},
"price": {
"min": {
"field": "price"
}
}
}
}
}
}
The size parameter you have mentioned before the query, is used to set the size for the query hits, and will not affect the aggregations bucket size.
Use the size parameter inside the parent aggregation just like you have mentioned in the sub-aggregation as "size":1
The modified query to get top 10 aggs is :
{
"size": "15",
"from": "0",
"query": {
"bool": {
"filter": [
{
"term": {
"category": "Cars"
}
},
{
"term": {
"location": "Sydney"
}
},
{
"term": {
"status": true
}
}
]
}
},
"sort": [
{
"_score": "desc"
},
{
"brand": "asc"
}
],
"aggs": {
"brand": {
"terms": {
"field": "brand",
"size": 10,
"order": {
"price": "asc"
}
},
"aggs": {
"brand": {
"top_hits": {
"size": 1,
"sort": [
{
"price": {
"order": "asc"
}
}
]
}
},
"price": {
"min": {
"field": "price"
}
}
}
}
}
}
Hope this helps.

Elasticsearch - filter geo_distance query

I have a mapping type with two fields : location (geo_point) and type (short).
I want to list my places by geo proximity and use this kind of query
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": "20km",
"location": {
"lat": 48.856614,
"lon": 2.3522219
}
}
}
}
},
"aggs": {
"types": {
"terms": {
"field": "type"
}
}
},
"post_filter": [],
"page": 1,
"size": 50,
"sort": [
{
"_geo_distance": {
"location": {
"lat": 48.856614,
"lon": 2.3522219
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
Is there any way to only include the first 2 places of a special type (e.g. type=2) ?
Add another clause to the filter like
{
"query": {
"bool": {
"filter": [{
"geo_distance": {
"distance": "20km",
"location": {
"lat": 48.856614,
"lon": 2.3522219
}
}
},
{
"term": {"type":"2"}
}]
}
},
"aggs": {
"types": {
"terms": {
"field": "type"
}
}
},
"post_filter": [],
"page": 1,
"size": 2,
"sort": [
{
"_geo_distance": {
"location": {
"lat": 48.856614,
"lon": 2.3522219
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}

Elasticsearch with range and exists filter

I have a ElasticSearch query to get every products within a set range. I would like to add a filter to select only documents which have the attribute "products". My tests with must exists had always error.
/zipcodes_at/zipcode/_search
{
"_source": [
"products"
],
"filter": {
"geo_distance": {
"distance": "100km",
"location": {
"lat": 48.232361,
"lon": 16.324659
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 48.232361,
"lon": 16.324695
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
Try this:
POST /zipcodes_at/zipcode/_search
{
"_source": [
"products"
],
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "products"
}
},
{
"geo_distance": {
"distance": "100km",
"location": {
"lat": 48.232361,
"lon": 16.324659
}
}
}
]
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 48.232361,
"lon": 16.324695
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
You should must use bool filter , and combine geo distance filter along with exist filter.
{
"_source": ["products"],
"query": {
"filtered": {
"filter": {
"bool": {
"must": [{
"exists": {
"field": "products"
}
}, {
"geo_distance_range": {
"from": 0,
"to": 100,
"distance_unit": "km",
"location": {
"lat": 40.73,
"lon": -74.1
}
}
}]
}
}
}
},
"sort": [{
"_geo_distance": {
"location": {
"lat": 48.232361,
"lon": 16.324695
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}]
}

Resources