How to write a conditional query with Elasticsearch? - 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

Related

How to combine must and must_not in elasticsearch with same field

i have elasticsearch 6.8.8, just for an example of my question. I want to create a query that gets me document with "Test" field with value "1", and i don't want to get "Test" field with value of "3", i know that i could write just the first expression without 3 and it will give me one document with value of "1". But i want to know, is there any way, that i can use must and must_not in the same time, on the same field and getting just the value of "1"?
I wrote this basic example to know what i mean:
{
"from": 0,
"query": {
"nested": {
"path": "attributes",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"attributes.key": {
"query": "Test"
}
}
},
{
"match": {
"attributes.value": {
"query": "1"
}
}
}
],
"must_not": [
{
"match": {
"attributes.key": {
"query": "Test"
}
}
},
{
"match": {
"attributes.value": {
"query": "3"
}
}
}
]
}
}
]
}
}
}
}
}
I use attributes as nested field with key-value field that use mapping as string type.
You'll need to leave out attributes.key:Test in the must_not because it filters out all Tests:
GET combine_flat/_search
{
"from": 0,
"query": {
"nested": {
"inner_hits": {},
"path": "attributes",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"attributes.key": {
"query": "Test"
}
}
},
{
"match": {
"attributes.value": {
"query": "1"
}
}
}
],
"must_not": [
{
"match": {
"attributes.value": {
"query": "3"
}
}
}
]
}
}
]
}
}
}
}
}
Tip: use inner_hits to just return the matched nested key-value pairs as opposed to the whole field.

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.

Should as filter context (OR without scoring in Elasticsarch possible?)

I am trying to setup most efficient way to build an OR without having a scoring, since I want to order my results by business values afterwards.
Unfortunately i don't get it done. :(
What I need:
COLOR=X AND ( title = Y OR description = Z)
What I tried (but it is malformed):
{
"query": {
"bool": {
"filter": [
{
"term": {
"colors.source_name": "braun"
}
},
{
"should": [
{
"term": {
"title": "sofa"
}
},
{
"term": {
"description": "sofa"
}
}
]
}
]
}
}
What I also tried, but it also provided results without "gartenlounge", and especially with scoring:
{
"query": {
"bool": {
"filter": [
{
"term": {
"colors.source_name": "braun"
}
}
],
"should": [
{
"term": {
"title": "sofa"
}
},
{
"term": {
"description": "sofa"
}
}
]
}
}
The following query should work for you:
{
"query": {
"bool": {
"filter": [
{"term": {
"colors.source_name": "braun"
}},
{"bool": {
"should": [
{"term": {"title": "sofa"}},
{"term": {"description": "sofa"}}
]
}}
]
}
}
}
You can nest a bool query inside the filter context, and should is only valid from within a bool clause.
It's an old reference sir, but it still checks out:
https://www.elastic.co/guide/en/elasticsearch/guide/current/combining-filters.html

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.

"boost" not working for "term" query

I'm running Elasticsearch 1.5.2 and trying the following query:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"gender": "male"
}
}
]
}
},
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"term": {
"top_users": 1,
"boost": 2
}
}
]
}
}
}
}
}
Everything is fine until I add the "boost": 2 to the should -> term part. The complete query is much more complex, that's why I need to boost, but the remaining queries don't make any difference: ES returns an error 400 if a term query gets a boost argument:
QueryParsingException[[index_name] [_na] query malformed, must start with start_object]
Any suggestions?
It should be like this:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"gender": "male"
}
}
]
}
},
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"term": {
"top_users": {
"value": "1",
"boost": 2
}
}
}
]
}
}
}
}
}

Resources