Elasticsearch DSL bool query for filtration - elasticsearch

I have an Elasticsearch DSL query as below
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"api": "A"
}
},
{
"match_phrase": {
"api": "B"
}
},
{
"match_phrase": {
"api": "C"
}
}
],
"minimum_should_match": 1
}
}
}
As I understand, this is something like
match if (api = A or api = B or api = C)
I want to add another condition checking a different field in the third check.
E.g match if (api = A or api = B or (api = C and another_field = D ) ) Any idea how to do this?

You can use a combination of bool/must query
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"api": "A"
}
},
{
"match_phrase": {
"api": "B"
}
},
{
"bool": {
"must": [
{
"match_phrase": {
"api": "C"
}
},
{
"match_phrase": {
"another_field": "D"
}
}
]
}
}
],
"minimum_should_match": 1
}
}
}

Related

Simplest way to query a elasticsearch index with chained conditions

I have an index of products on which I want to find all the products who fulfill conditions , such as :
((type = "orange" and price > 10) or (type = "apple" and price > 8)) and on_sale=True.
What about
(type = "orange" or type = "apple") and (price <= 25 or on_sale=True) .
You need to combine bool clauss, with "must" and "should".
Find below the required query for the first statement
GET _search
{
"query": {
"bool": {
"must": [
{
"term": {
"on_sale": {
"value": "True"
}
}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"type": {
"value": "orange"
}
}
},
{
"range": {
"price": {
"gte": 10
}
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"type": {
"value": "apple"
}
}
},
{
"range": {
"price": {
"gte": 8
}
}
}
]
}
}
]
}
}
]
}
}
}
It is just about wrapping "must" or "Should" clauses into one another as required. You need a little bit of practise to figure out how to chain them. But literally any combination can be queried using this kind of syntax.
For the second query:
{
"query": {
"bool": {
"must": [
{
"terms": {
"type": [
"ornage",
"apple"
]
}
},
{
"bool": {
"should": [
{
"term": {
"on_sale": {
"value": "True"
}
}
},
{
"range": {
"price": {
"gte": 10
}
}
}
]
}
}
]
}
}
}
When you need "and" use "MUST", when you need "or" use "SHOULD".
HTH.

Does elasticsearch support SQL like OR conditions

For example in SQL I would write (a AND b) OR (c AND d). But I can't find a direct analogue in elasticsearch.
Yes, it's doable via bool/should, like this:
{
"query": {
"bool": {
"should": [
{
"bool": {
"filter": [
{
"match": {
"field1": "foo"
}
},
{
"match": {
"field2": "bar"
}
}
]
}
},
{
"bool": {
"filter": [
{
"match": {
"field1": "baz"
}
},
{
"match": {
"field2": "fox"
}
}
]
}
}
]
}
}
}
In Elasticsearch,
should is equivalent to OR in SQL and must is equivalent to AND.
So the following query is equivalent to your SQL query and will fetch first 10 results.
(A=a AND B=b) OR (C=c AND D=d)
GET /<indexName>/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"bool": {
"must": [
{
"match": {
"A": "a"
}
},
{
"match": {
"B": "b"
}
}
]
}
}
},
{
"match": {
"bool": {
"must": [
{
"match": {
"C": "c"
}
},
{
"match": {
"D": "d"
}
}
]
}
}
}
]
}
},
"from": 0,
"size": 10,
"sort": [],
"aggs": {}
}
Reference: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html

Elasticsearch- nested conditional statements

I would like to develop multiple if else condition like this :
if(condition 1)
{
process 1
}
else
{
if(condition 2.1)
{
process 2
}
else (condition 2.2)
{ process 3
}
}
is bool with must and should the optimized way to do it or can script be used? As my query is already huge, since it has fuzziness and wildcard already.
Thanks
I think you can use painless script query for your use case. Bool must query will not work in this case I think.
You can refer this page for how to use if else in the script query
.https://www.elastic.co/guide/en/elasticsearch/painless/6.0/painless-examples.html
GET /books/_search
{
"_source": [
"id",
"name",
"user",
"privacy"
],
"query": {
"bool": {
"must": [
{
"term": {
"status": {
"value": 1
}
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{ //if
"bool": {
"must": [
{
"term": {
"user.privacy.mode": {
"value": 0
}
}
},
{
"term": {
"privacy.mode": {
"value": 0
}
}
}
]
}
},
{//else if
"bool": {
"must": [
{
"term": {
"user.privacy.mode": {
"value": 2
}
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{// if
"nested": {
"path": "readers",
"query": {
"match": {
"readers.id": "621120dc86b8920019295363"
}
}
}
},
{ // else
"nested": {
"path": "buyers",
"query": {
"match": {
"buyers.purchase.id": "621120dc86b8920019290f50"
}
}
}
}
]
}
}
]
}
},
{// else if
"bool": {
"must": [
{
"term": {
"privacy.mode": {
"value": 2
}
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"nested": {
"path": "readers",
"query": {
"match": {
"readers.id": "621120dc86b89200195373"
}
}
}
},
{
"nested": {
"path": "buyers",
"query": {
"match": {
"buyers.purchase.id": "621120dc86b892001929036350"
}
}
}
}
]
}
}
]
}
}
]
}
}
],
"filter": {
"bool": {
"must_not": [
{
"term": {
"user.privacy.mode": 1
}
},
{
"term": {
"privacy.mode": 1
}
}
]
}
}
}
}
}

Using multiple Should queries

I want to get docs that are similar to multiple "groups" but separately. Each group has it's own rules (terms).
When I try to use more than one Should query inside a "bool" I get items that are a mix of both Should's terms.
I want to use 1 query total and not msearch for example.
Can someone please help me with that?
{
"explain": true,
"query": {
"filtered": {
"filter": {
"bool": {
"must_not": [
{
"term": {
"p_id": "123"
}
},
{
"term": {
"p_id": "124"
}
}
]
}
},
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"term": {
"cat": "1"
}
},
{
"term": {
"cat": "2"
}
},
{
"term": {
"keys": "a"
}
},
{
"term": {
"keys": "b"
}
}
]
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"term": {
"cat": "6"
}
},
{
"term": {
"cat": "7"
}
},
{
"term": {
"keys": "r"
}
},
{
"term": {
"keys": "u"
}
}
]
}
}
]
}
}
}
},
"from": 0,
"size": 3
}
You can try using a terms aggregation on multiple fields with scripting and add a top hits aggregation as a sub-aggregation. Be warned this will be pretty slow. Add this after the query/filter and adjust the size parameter as needed
"aggs": {
"Cat_and_Keys": {
"terms": {
"script": "doc['cat'].values + doc['keys'].values"
},
"aggs":{ "separate_docs": {"top_hits":{"size":1 }} }
}
}

How to combine multiple bool queries in elasticsearch

I want to create the equivalent of the following query -
(city = 'New York' AND state = 'NY') AND ((businessName='Java' and businessName='Shop') OR (category='Java' and category = 'Shop'))
I tried different combinations of bool queries using must and should but nothing seems to be working. Can this be done?
How about something like this:
{
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"term": {
"city": "New york"
}
},
{
"term": {
"state": "NY"
}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"businessName": "Java"
}
},
{
"term": {
"businessName": "Shop"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"category": "Java"
}
},
{
"term": {
"category": "Shop"
}
}
]
}
}
]
}
}
]
}
}
}

Resources