With Elasticsearch, how to use an OR instead of AND within filter->terms query? - elasticsearch

I have this following query with elastic:
{
"query": {
"bool": {
"filter": [{
"terms": {
"participants.group": ["group1","group2"]
}
}, {
"range": {
"recordDate": {
"gte": "2020-05-14 00:00:00.000",
"lte": "2020-07-22 20:30:56.566"
}
}
}]
}
}
}
Currently, this finds records with participants with group "group1" and "group2".
How to change the query so it finds records with participants from "group1" or "group2?
Is it possible to do it without changing the structure of the query?

I'm assuming that the field participants.group is of keyword type and not text type.
Assuming that, the query you have roughly translates to (group1) or (group2) or (group1 and group2).
All you need to do is modify the query as below and add a must_not clause like below:
POST my_filter_index/_search
{
"query": {
"bool": {
"filter": [
{
"bool": {
"must": [
{
"range": {
"recordDate": {
"gte": "2020-05-14 00:00:00.000",
"lte": "2020-07-22 20:30:56.566"
}
}
}
],
"should": [
{
"terms": {
"participants.group": ["group1", "group2"]
}
}
]
}
}
],
"must_not": [
{
"bool": {
"must": [
{
"term": {
"participants.group": "group1"
}
},
{
"term": {
"participants.group": "group2"
}
}
]
}
}
]
}
}
}
Let me know if that works!

Related

need something like coalesce in elasticsearch

My current elasticsearch query is-
{
"must": [
{
"range": {
"firstClosedAt": {
"gte": 1667948400000,
"lte": 1668034800000
}
}
},
{
"term": {
"status": "CLOSED"
}
}
I want to modify it such that if "firstClosedAt" is null or not present then look for "closedAt".
Just like we have coalesce("firstClosedAt","closedAt") in sql
Help would be appreciated
There's no coalesce equivalent in ES, but you can do the query like below, which can read like: "either use firstClosedAt OR use closedAt if firstClosedAt does not exist":
{
"query": {
"bool": {
"filter": [
{
"term": {
"status": "CLOSED"
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"firstClosedAt": {
"gte": 1667948400000,
"lte": 1668034800000
}
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "firstClosedAt"
}
},
"filter": {
"range": {
"closedAt": {
"gte": 1667948400000,
"lte": 1668034800000
}
}
}
}
}
]
}
}
]
}
}
}
You could, however, create a much simpler query if you create another date field at indexing time which would either take the value of firstClosedAt or closedAt if firstClosedAt does not exist

combine two queries of elasticsearch?

I have a "date_created_tranx" and "phone_number_cust" fields. Few entries of date_created_tranx are null . I want to have particular phone_number within date_range and with null value.
a = {
"query": {
"bool": {
"must": [
{
"range": {
"date_created_tranx": {
"gte": "2019-12-01",
"lte": "2020-05-07"
}
}
},
{
"regexp": {
"phone_number_cust": ".*702625.*"
}
}
]
}
}
}
b = {
"query": {
"bool": {
"must": [{
"regexp": {
"phone_number_cust": ".*702625.*"
}
}],
"must_not": [{
"exists": {
"field": "date_created_tranx"
}
}
]
}
}
}
How to combine these ??
I cannot call it twice because The result is paginated
I am totally new to elastic search . Any leads will be helpful.
I tried
doc2 = {
"query" :{
"bool" : {
"must":[
a,
b
]
}
}
}
It throws
Error: RequestError: RequestError(400, 'parsing_exception', 'no [query] registered for [query]')
The query you're looking for is this one, i.e.:
We have a constraint on the phone number and we also check that either the date_created_tranx is within bounds or does not exist (i.e. is null).
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"date_created_tranx": {
"gte": "2019-12-01",
"lte": "2020-05-07"
}
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "date_created_tranx"
}
}
}
}
],
"filter": [
{
"regexp": {
"phone_number_cust": ".*702625.*"
}
}
]
}
}
}

Elasticsearch query: range query on two fields, but one is optional field

I need to search my index based on a timestamp.
The documents have these field combinations:
start_time and end_time
or
just start_time (no end_time field)
Pseudo query: .
For a given timestamp, I wish to return all documents where an id matches, and also:
timestamp >= start_time && timestamp < end_time
but if there is no end_time field, then the query needs to be this:
(not exists end_time) && (timestamp > start_time)
Elastic query .
This is where I am going mad. I can't get an elastic query equivilent to that pseudo query above. Perhaps I am approaching it the wrong way (entirely possible). Here is what I have:
{
"query": {
"bool": {
"must": [
{
"term": {
"id_s": "SomeIdValue"
}
},
{
"bool": {
"should": [
{
"must": [
{
"must_not": [
{
"exists": {
"field": "end_time_dt"
}
}
]
},
{
"range": {
"start_time_dt": {
"lte": "2019-07-12T03:20:22"
}
}
}
]
},
{
"filter": [
{
"range": {
"start_time_dt": {
"lte": "2019-07-12T03:20:22"
}
}
},
{
"range": {
"end_time_dt": {
"gte": "2019-07-12T03:20:22"
}
}
}
]
}
]
}
}
]
}
}
}
But this gives me [must] query malformed, no start_object after query name
How do I construct this query? Am I on the right track?
thanks in advance!
Your query is syntactically wrong. The correct query would be:
{
"query": {
"bool": {
"filter": [
{
"term": {
"id_s": "SomeIdValue"
}
},
{
"bool": {
"should": [
{
"bool": {
"must_not": [
{
"exists": {
"field": "end_time_dt"
}
}
],
"must": [
{
"range": {
"start_time_dt": {
"lte": "2019-07-12T03:20:22"
}
}
}
]
}
},
{
"bool": {
"must": [
{
"range": {
"start_time_dt": {
"lte": "2019-07-12T03:20:22"
}
}
},
{
"range": {
"end_time_dt": {
"gte": "2019-07-12T03:20:22"
}
}
}
]
}
}
]
}
}
]
}
}
}
There is a slight mistake in the logic. Ideally, comparison should be like this gte start_time_dt and lte end_time_dt. You did other way round so that translates to timestamp <= start_time && timestamp > end_time.
The correct query is
{
"query": {
"bool": {
"filter": [
{
"term": {
"id_s": "SomeIdValue"
}
},
{
"bool": {
"should": [
{
"bool": {
"must_not": [
{
"exists": {
"field": "end_time_dt"
}
}
],
"must": [
{
"range": {
"start_time_dt": {
"gte": "2019-07-12T03:20:22"
}
}
}
]
}
},
{
"bool": {
"must": [
{
"range": {
"start_time_dt": {
"gte": "2019-07-12T03:20:22"
}
}
},
{
"range": {
"end_time_dt": {
"lte": "2019-07-12T03:20:22"
}
}
}
]
}
}
]
}
}
]
}
}
}
Hope this helps!!
I believe this block should be must not should as mentioned in the answer. The reason I say is both those conditions: must ( not exists AND range ) is what the OP intention I believe
{
"bool": {
"must": [ <====== mentioned it as should
{
"bool": {
"must_not": [
{
"exists": {
"field": "end_time_dt"
}
}
],
"must": [
{
"range": {
"start_time_dt": {
"lte": "2019-07-12T03:20:22"
}
}
}
]
}
},

Use of range in Elasticsearch query

Below is the elastic search query. I need to use both the range and missing in a query.How can I change the below query
{
"query": {
"bool": {
"must": [
{
"constant_score": {
"filter": {
"missing": {
"field": "url"
}
}
}
}
],
"should": []
}
},
"_source": [
"id",
"com_name",
"website",
"_foundation._rating"
]
}
I need to add range to the above query. Kindly help me add the below section to the above query
"range": {
"_foundation._rating": {
"gte": 1,
"lte": 4
}
I suspect that the query you need is the following, i.e. the url field must be missing and the _foundation._rating field must be between and 1 and 4 (inclusive):
{
"query": {
"bool": {
"must": [
{
"missing": {
"field": "url"
}
},
{
"range": {
"_foundation._rating": {
"gte": 1,
"lte": 4
}
}
}
]
}
},
"_source": [
"id",
"com_name",
"url",
"_foundation._rating"
]
}
Based on the version of your elastic search, if you are using 5.x, you must use exists inside a must_not clause.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html
Try the below query:
{
"query": {
"range": {
"bool": {
"must": [
{
"term": {
"_foundation._rating": {
"gte": 1,
"lte": 4
}
}
}
],
"must_not": {
"exists": {
"field": "url"
}
}
}
}
}
}

Elasticsearch: execute a filter on nested document only if it exists

I am using ES 2.3 and have a query in which filter section looks as follows:
"filter": {
"query": {
"bool": {
"must": [
{
"nested": {
"path": "employees",
"query": {
"bool": {
"must": [
{
"range": {
"employees.max_age": {
"lte": 50
}
}
},
{
"range": {
"employees.min_age": {
"gte": 20
}
}
}
]
}
}
}
},
{
"exists": {
"field": "employees"
}
},
{
#....other filter here based on root document, not on nested employee document
}
]
}
}
}
}
I have a filter, where I check some conditions in the nested document "employees" in a bigger document called company, But I want to run this filter, only if "employees" object exists, as some of the document may not have that nested document at all. So I added , {"exists": {"field": "employees"}}
but this doesn't seem to work. Any idea what change I should make to get it work?
You can do it like this. However, if documents don't have the employees field, they will not be picked up anyway, so I'm not sure why you want/need that exists query in the first place.
{
"filter": {
"query": {
"bool": {
"must": [
{
"nested": {
"path": "employees",
"query": {
"exists": {
"field": "employees"
}
}
}
},
{
"nested": {
"path": "employees",
"query": {
"bool": {
"must": [
{
"range": {
"employees.max_age": {
"lte": 50
}
}
},
{
"range": {
"employees.min_age": {
"gte": 20
}
}
}
]
}
}
}
}
]
}
}
}
}

Resources