elasticsearch nested range query - elasticsearch

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
}
}
}
}
}
]
}
}]
}
}
}

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" } }]]
}
},

Custom sort after score calculation and the value of specific field

Need help to understand sorting in a query where _score is either 0 or 1 based on some conditions
but there is also an additional_filed type integer, sort should be in the order of _score * additional_field
sample index
PUT /product_t
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"placed" :{
"type": "integer"
},
"store" : {
"type": "nested"
}
}
}
}
sample document
PUT /product_t/_doc/10
{
"name": "awesome",
"count_sold": 199,
"stock": [
{
"id": 1,
"count": 10
},
{
"id": 2,
"count": 5
},
{
"id": 3,
"count": 0
}
]
}
Query Used :
POST /product_t/_search
{
"from": 0,
"size": 100,
"timeout": "300ms",
"query": {
"bool": {
"filter": [
{
"match": {
"name": {
"value": "awesome"
}
}
},
{
"nested": {
"path": "stock",
"query": {
"bool": {
"must": [
{
"match": {
"stock.id": 3
}
}
]
}
}
}
}
],
"should": [
{
"constant_score": {
"filter": {
"nested": {
"path": "stock",
"query": {
"bool": {
"must": [
{
"match": {
"stock.id": 3
}
},
{
"range": {
"stock.count": {
"gt": 0
}
}
}
]
}
}
}
},
"boost": 1
}
},
{
"constant_score": {
"filter": {
"nested": {
"path": "stock",
"query": {
"bool": {
"must": [
{
"match": {
"stock.id": 3
}
},
{
"range": {
"stock.count": {
"lte": 0
}
}
}
]
}
}
}
},
"boost": 0
}
}
]
}
}
}
count_sold is additional field
You can use script sort
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "doc['count_sold'].value * _score"
},
"order": "asc"
}
}

How to write complex ElasticSearch query

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"
}
}
}
}
]
}
}
}

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 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