How to write complex ElasticSearch query - elasticsearch

I want to return the data from ElasticSearch using the range query.
My Condition is something like this.
((Range(Price and Discount) OR Range(Price) AND Filter(Must1) AND Filter(Must2))
The issue I am facing is that some document contains both price and discount but some only contains Price. I need a query to get data according to the specified range. So, it returns the discount field but not the specified range which I want.
right now I am using this query.
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"range": {
"discount": {
"gte": 10,
"lte": 12
}
}
},
{
"range": {
"price": {
"gte": 10,
"lte": 12
}
}
}
]
}
},
{
"bool": {
"should": [
{
"range": {
"discount": {
"gte": 10,
"lte": 12
}
}
},
{
"range": {
"price": {
"gte": 10,
"lte": 12
}
}
}
]
}
}
]
}
},
{
"terms": {
"Category": [
"123"
]
}
},
{
"nested": {
"path": "the_path",
"query": {
"bool": {
"must": {
"match": {
}
},
"filter": [
]
}
}
}
}
]
}
}
Please help me with this I am stuck with it from past few days.

Based on the condition you have given, following DSL Query will be created
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"range": {
"price": {
"gte": 10,
"lte": 20
}
}
},
{
"range": {
"deiscount": {
"gte": 10,
"lte": 20
}
}
}
]
}
},
{
"range": {
"price": {
"gte": 10,
"lte": 20
}
}
}
]
}
},
{
"bool": {
"filter": {
"term": {
"user.id": "kimchy"
}
}
}
},
{
"bool": {
"filter": {
"term": {
"user.id": "kimchy"
}
}
}
}
]
}
}
}

Related

Issue with ElasticSearch 8.4 query

Hi i have recently been busy reworking our old and outdated ES now um running 8.4 and im trying to create a similar query to what i had in the old one. But i have a hard time finding examples or the right documentation
This is an example what we had on version 1.7:
I have tried te exact same in 8.4 now
{
"index": "vehicles",
"type": "vehicle",
"body": {
"from": "0",
"size": 30,
"query": {
"filtered": {
"query": { "match_all": [] },
"filter": {
"bool": {
"must": [
{
"bool": {
"should": [
[
{ "term": { "make.untouched": "IVECO" } },
{ "term": { "make.untouched": "VOLKSWAGEN" } }
]
]
}
},
{
"bool": {
"should": [[{ "term": { "type_serie.untouched": "DAILY" } }]]
}
},
{
"bool": {
"should": [[{ "term": { "filters.header.camper": "true" } }]]
}
},
{ "range": { "days_sold": { "gte": 0, "lt": 2 } } },
{ "range": { "days_on_stock": { "gte": 3 } } },
{ "range": { "price": { "gt": 0 } } },
{ "range": { "price_trader": { "gt": 0 } } },
{ "term": { "show_in_search": true } }
],
"must_not": [
{ "term": { "offer_code": "z" } },
{ "term": { "stockingtype": "a" } },
{ "term": { "stockingtype": "v" } },
{ "term": { "stockingtype": "z" } },
{ "term": { "stockingtype": "p" } }
]
}
}
}
},
"sort": [
{ "_score": "desc" },
{ "days_on_stock": "asc" },
{ "price": "asc" }
]
}
}
You have double arrays and that's the issue (older versions were more permissive):
"should": [
remove this -->[
{ "term": { "make.untouched": "IVECO" } },
{ "term": { "make.untouched": "VOLKSWAGEN" } }
remove this -->]
]
Same here
same here same here
{ | |
"bool": { v v
"should": [[{ "term": { "type_serie.untouched": "DAILY" } }]]
}
},
{
"bool": {
"should": [[{ "term": { "filters.header.camper": "true" } }]]
}
},

elasticsearch nested range query

Suppose i want this structure for a document:
{
"hours": {
"open": [
{
"start": 10,
"end": 19
},
{
"start": 21,
"end": 29
}
...
],
"closed": [
{
"start": 100,
"end": 199
},
{
"start": 201,
"end": 299
}
...
]
}
}
whose index has this mapping:
{
"mappings": {
"_doc": {
"properties": {
"hours": {
"properties": {
"open": {
"type": "nested",
"properties": {
"start": { "type": "integer" },
"end": { "type": "integer" }
}
},
"closed": {
"type": "nested",
"properties": {
"start": { "type": "integer" },
"end": { "type": "integer" }
}
}
}
}
}
}
}
}
In the Elasticsearch Query DSL, how do i find all documents where 20 lies inside an open segment and not inside a closed segment. The query I tried was incorrect.
failed query
{
"query": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"nested": {
"path": "hours.open",
"query": {
"range": {
"hours.open.start": { "lte": 20 }
}
}
}
},
{
"nested": {
"path": "hours.open",
"query": {
"range": {
"hours.open.end": { "gte": 20 }
}
}
}
}
]
}
},
{
"bool": {
"must_not": [
{
"bool": {
"must": [
{
"nested": {
"path": "hours.closed",
"query": {
"range": {
"hours.closed.start": { "lte": 20 }
}
}
}
},
{
"nested": {
"path": "hours.closed",
"query": {
"range": {
"hours.closed.end": { "gte": 20 }
}
}
}
}
]
}
}
]
}
}
]
}
}
}
whats wrong with my query? it is returning this document which is not what i intended. 20 does not lie inside an open segment.
I finally got it working. The following is the correct query:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "hours.open",
"query": {
"bool": {
"must": [
{ "range": { "hours.open.start": { "lte": 20 } } },
{ "range": { "hours.open.end": { "gte": 20 } } }
]
}
}
}
}
],
"must_not": [
{
"nested": {
"path": "hours.closed",
"query": {
"bool": {
"must": [
{ "range": { "hours.closed.start": { "lte": 20 } } },
{ "range": { "hours.closed.end": { "gte": 20 } } }
]
}
}
}
}
]
}
}
}
With that said, it looks like my original attempt was wrong because there were two different hours.open nested path queries and likewise two different hours.closed nested path queries. The parser must only take one of them for a single path.
Seems like you need to swap lte and gte:
"hours.open.start": { "gte": 20 }
"hours.open.end": { "lte": 20 }
and same for the closing times:
"hours.closed.start": { "gte": 20 }
"hours.closed.end": { "lte": 20 }
Edit:
The must and must_not need to be part of the same bool query:
{
"query": {
"bool": {
"must": [{
"nested": {
"path": "hours.open",
"query": {
"range": {
"hours.open.start": {
"gte": 20
}
}
}
}
},
{
"nested": {
"path": "hours.open",
"query": {
"range": {
"hours.open.end": {
"lte": 20
}
}
}
}
}
],
"must_not": [{
"bool": {
"must": [{
"nested": {
"path": "hours.closed",
"query": {
"range": {
"hours.closed.start": {
"gte": 20
}
}
}
}
},
{
"nested": {
"path": "hours.closed",
"query": {
"range": {
"hours.closed.end": {
"lte": 20
}
}
}
}
}
]
}
}]
}
}
}

query malformed, no start_object after query name

I am running this query against AWS Elasticsearch 5.1 and getting a malformed query error. Here is the body of the request. I am basically just checking if the field exists during the time range.
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"#timestamp": {
"gt": "2017-03-21T15:37:08.595919Z",
"lte": "2017-04-21T15:52:08.595919Z"
}
}
},
{
"query": [
{
"query_string": {
"query": "_exists_: $event.supplier"
}
}
]
}
]
}
}
}
},
"sort": [
{
"#timestamp": {
"order": "asc"
}
}
]
}
The second must statement was incorrect:
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"#timestamp": {
"gt": "2017-03-21T15:37:08.595919Z",
"lte": "2017-04-21T15:52:08.595919Z"
}
}
},
{
"query_string": {
"query": "_exists_: $event.supplier"
}
}
]
}
}
}
},
"sort": [
{
"#timestamp": {
"order": "asc"
}
}
]
}

How to use Aggregation by range time and terms

Idea: Search Top events on specific range and order by start_time. Like:
{
"from": 0,
"size": 7,
"query": {
"filtered": {
"query": { "match_all": {} },
"filter": {
"and": [
{ "bool": { "must_not": { "term": { "status": "OK" } } } },
{ "bool": { "must": { "term": { "is_blocked": false } } } }, {
"range": {
"start_time": {
"gte": "2016-01-01",
"lte": "2016-03-01"
}
}
}, {
"bool": {
"must": {
"geo_distance": {
"distance": "150km",
"coordinates": "xx.xxx, zz.zz "
}
}
}
}
]
}
}
},
"sort": [{ "start_time": "asc" },
{ "attending": "desc" }
]
}
I quite new on this concept of aggregations so still with basic problems to understand
I wanna 7 results of top events for the next 2 months. So I have two attributes to look. The max of people attending(attendings) is the definition of Top, but also I wanna order this by time(start_time: asc)
What I start to wrote but is wrong:
{
"aggs": {
"aggs": {
"event_interval": {
"date_histogram": {
"field": "start_time",
"interval": "2M",
"format": "dateOptionalTime"
}
},
"max_attending": { "max": { "field": "attending" } },
"_source": {
"include": [
"name"
]
}
}
}
}
I'm not sure you need to be using an aggregation to get what you are looking for, I think that a simple query can yield the results you would like to see, try this:
{
"size": 7,
"sort": {
"attending": {
"order": "desc"
}
},
"query": {
"bool": {
"filter": [
{
"range": {
"start_time": {
"gte": "now-2M",
"lte": "now"
}
}
}
]
}
}
}

How to use range post_filter in elasticsearch

I cannot find examples of the syntax anywhere and the following does not work:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{ "term": { "category": "catname" }}
]
}
}
}
},
"post_filter": {
"terms": {"type": ["foo1", "foo2"] },
"range": { "price": { "gte": 300, "lte": 600 } }
}
}
You just need to wrap all your terms filters in an additional bool/must filter:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"category": "catname"
}
}
]
}
}
}
},
"post_filter": {
"bool": {
"must": [
{
"terms": { "type": [ "foo1", "foo2" ] }
},
{
"range": { "price": { "gte": 300, "lte": 600 } }
}
]
}
}
}

Resources