How to combine more than two filters in elasticsearch? - elasticsearch

I want to write query like this for elasticsearch 1.7:
SELECT * FROM prods WHERE
id=1 AND
name='flower' AND
(count_usd=1 OR prise_usd=5) AND
(count_eur=1 OR prise_eur=5)
?
I've read about nested bool ( https://www.elastic.co/guide/en/elasticsearch/guide/1.x/combining-filters.html ) but cannot apply it to my context :-(

You can nest a bool query within a bool query to achieve this kind of filtering:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [{
"term": {"name":"flower"}
}],
"should": [{
"bool": {
"should": [{
"term": {
"count_usd": 1
}
}, {
"term": {
"prise_usd": 5
}
}]
}
}, {
"bool": {
"should": [{
"term": {
"count_eur": 1
}
}, {
"term": {
"prise_eur": 5
}
}]
}
}]
}
}
}
}
}
Note that should clause acts like an OR: at least one of the subclauses in a should must be true to match.

Related

Is there any good boolean query parser for ElasticSearch?

Is there any library in ElasticSearch or other open-source, that transforms the boolean query into a ElasticSearch query?
With the typical boolean query expressions (AND, OR, "", *, ?) to transform into the "json" query for ElasticSearch and create the "musts", "shoulds", etc...
I mean, for example, to transform this:
(city = 'New York' AND state = 'NY') AND ((businessName='Java' and businessName='Shop') OR (category='Java' and category = 'Shop'))
into 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"
}
}
]
}
}
]
}
}
]
}
}
}
There's a Python library called luqum that does exactly what you need.
That library will parse the Lucene expression into an abstract syntax tree. You can then use that tree and generate the Elasticsearch JSON DSL equivalent query.

Will ElasticSearch performance differ if we have multiple nested queries

In general, if we need to do an OR condition in elasticsearch within one nested type, let's say, we do query like below :
Query 1:
{
"query": {
"bool": {
"must": [{
"nested": {
"query": {
"bool": {
"must": [{
"bool": {
"should": [{
"match": {
"descTags.device": {
"query": "abc"
}
}
}, {
"match": {
"descTags.device": {
"query": "xyz"
}
}
}]
}
}]
}
},
"path": "descTags"
}
}]
}
}
}
The above query has one nested and have OR condition within this one nested type.
Representing below the same query with two nested blobs :
Query 2:
{
"query": {
"bool": {
"must": [{
"bool": {
"should": [{
"bool": {
"must": [{
"nested": {
"query": {
"bool": {
"must": [{
"match": {
"descTags.Modality": {
"query": "abc"
}
}
}]
}
},
"path": "descTags",
}
}]
}
}, {
"bool": {
"must": [{
"nested": {
"query": {
"bool": {
"must": [{
"match": {
"descTags.Modality": {
"query": "xyz"
}
}
}]
}
},
"path": "descTags"
}
}]
}
}]
}
}]
}
}
}
Will there be any difference in performance between query1 and query2 just because we are having nested blob multiple times?
EDIT 1:
As per the below comments (#kamal), I am simplifying my question here..
Will there be any difference in performance if the boolean operation is done between "attributes that belong to same nested type, declaring the nested type only once" vs "attributes that belong to same nested type, declaring the nested type twice, once for each attribute".
like below :
1.
nested :
or :
attribute1
attribute2
vs
2.
or :
nested :
attribute1
nested :
attribute2

passing multiple combination query in elastic search

`"query": {
"function_score": {
"query": {
"bool": {
"must": [],
"should": [],
"filter": [
{
"terms": {
"category": "type-1",
"product": "product-A"
},
"terms": {
"category": "type-2",
"product": "product-B"
}
}
]
}
},
"functions": []
}
},`
I want to pass multiple combination query like above is it possible, what should be the correct query format
in sql my query would be
select * from product where (category='type1' and product=product-A) or (category='type2' and product=product-B) or (category='type3' and product=product-C)
i want to replicate above query
If you want to make a OR statement in a bool query you should is a nested bool query with multiple should clause.
so try :
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [],
"should": [],
"filter": [
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"category": "type-1"
}
},
{
"term": {
"product": "product-A"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"category": "type-2"
}
},
{
"term": {
"product": "product-B"
}
}
]
}
}
]
}
}
]
}
}
}
},
"functions": []
}
and if you have no must clause you can move your filters clauses into the main should as only document that matchs at least one of the clause will match.

How to write a conditional query with Elasticsearch?

I have a simple JSON query for Elasticsearch that looks like this:
"query": {
"bool": {
"must": { "match": { "id": "1" }} ,
"must": { "match": { "tags.name": "a1"}}
}
}
How can I execute the second 'must' criteria ONLY if the value ('a1' in this case) is not empty?
You can achieve it using the following -
{
"query": {
"bool": {
"must": [
{
"match": {
"id": "1"
}
},
{
"bool": {
"should": [
{
"missing": {
"field": "tags.name"
}
},
{
"match": {
"tags.name": "a1"
}
}
]
}
}
]
}
}
}
I don't think "missing" can be used in the latest versions of elasticsearch.
But one can use Conditional Clauses instead.
https://www.elastic.co/guide/en/elasticsearch/reference/6.3/search-template.html#_conditional_clauses

Bool filter and SHOULD and MUST combinations

I have a little confusion about the usage SHOULD and MUST in bool queries. When you have several filters in SHOULD and MUST clauses, can they be place at the same level or they should be nested?
Below is a simplified version of my data and the two queries that I tested, first one failing and the latter working. In real practice, I have many filters in MUST and SHOULD.
I start to believe that if one wants to combine several SHOULD and MUST filters, the outer one must always be SHOULD. Is this a correct assumption? And in case I wanted to use a MUST_NOT, where should it be placed in this context?
My data:
_index,_type,_id,_score,_source.id,_source.type,_source.valueType,_source.sentence,_source.location
"test","var","0","1","0","study","text","Lorem text is jumbled","spain"
"test","var","1","1","1","study","text","bla bla bla","spain"
"test","var","2","1","2","schema","decimal","ipsum","germany"
"test","var","3","1","3","study","integer","lorem","france"
Here is the failing query:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": {
"terms": {
"location": [
"germany"
]
}
},
"should": {
"terms": {
"valueType": [
"integer"
]
}
}
}
}
}
}
}
Here is my WORKING query returning IDs 2 and 3:
{
"query": {
"bool": {
"should": [
{
"terms": {
"location": [
"germany"
]
}
},
{
"bool": {
"must": [
{
"terms": {
"valueType": [
"integer"
]
}
}
]
}
}
]
}
}
}
Many thanks.
First need to understand meaning of filters.
Compound Filter:
must clauses are required (and)
should clauses are optional (or)
So in first block you are checking term in must(and). So this term must be in result set. and should(or) cond 2 may or may not in result set.
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": {
....... Cond 1
},
"should": {
....... Cond 2
}
}
}
}
}
}
In your working scenario you are query working because should checking Cond 1 OR Cond 2.
{
"query": {
"bool": {
"should": [ // OR
{
...... Cond 1
},
{
...... Cond 2
}
]
}
}
}

Resources