Elasticsearch Add additional condition if type is different - elasticsearch

GET test/_search
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"term": {
"type": "fragment"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"term": {
"type": "cf"
}
},
{
"range" :{
"start": {
"gte": 1,
"lte": 5
}
}
}
]
}
}
]
}
}
}
I am looking for two documents, one which has fragment id = 1, and type = fragment, whereas another where fragment id = 1, type = "cf" and start between 1 and 5.
The above query is doing the job, but I need to write type and fragment id twice. Is there a way I can add range condition only when the type is cf, basically clubbing both bools in one ?

This is the query you're looking for:
{
"query": {
"bool": {
"filter": [
{
"term": {
"fragmentId": "1"
}
}
],
"minimum_should_match": 1,
"should": [
{
"term": {
"type": "fragment"
}
},
{
"bool": {
"filter": [
{
"term": {
"type": "cf"
}
},
{
"range": {
"start": {
"gte": 1,
"lte": 5
}
}
}
]
}
}
]
}
}
}

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.

If Else Elasticsearch

I have two sets of documents, which are joined by fragmentId. I have written a query that pulls both documents, but I am thinking is there any other way to write it.
first set Document - There could be only one document which has type = fragment and fragmentId = 1
{
"fragmentId": "1",
"type" : "fragment"
}
The second kind of documents - There could be multiple such documents, separated by start and end values. In the query, I will be passing a value and only document inside that range should come.
Doc-1
{
"fragmentId" : "1",
"type": "cf",
"start": 1,
"end": 5
}
Doc- 2
{
"fragmentId" : "1",
"type": "cf",
"start": 6,
"end": 10
}
In the result, I want the first set document, then from the second set only the document which has a specific start and end values.
Here is the query, which is working for me-
GET test/_search
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"term": {
"type": "fragment"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"term": {
"type": "cf"
}
},
{
"range" :{
"start": {
"gte": 1,
"lte": 5
}
}
}
]
}
}
]
}
}
}
Is there a way to re-write this query in more simple form, so that first document is always picked, with the range matching document from the second set, basically a join operation on fragmentId?
Are you looking for something like this?
GET test/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"term": {
"type": "fragment"
}
},
{
"bool": {
"must": [
{
"term": {
"type": "cf"
}
},
{
"range": {
"start": {
"gte": 1,
"lte": 5
}
}
}
]
}
}
]
}
}
]
}
}
}
This query translates to :
(fragmentId = 1 AND (type = fragment OR (type = cf AND start is within 1 and 5)))

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

ElasticSearch ignoring sort when filtered

ElasticSearch Version: 0.90.1, JVM: 1.6.0_51(20.51-b01-457)
I'm trying to do two things with my ElasticSearch query: 1) filter the results based on a boolean (searchable) and "open_date < tomorrow" and 2) two sort by the field "open_date" DESC
This produces the following query:
{
"query": {
"bool": {
"should": [
{
"prefix": {
"name": "foobar"
}
},
{
"query_string": {
"query": "foobar"
}
},
{
"match": {
"name": {
"query": "foobar"
}
}
}
],
"minimum_number_should_match": 1
},
"filtered": {
"filter": {
"and": [
{
"term": {
"searchable": true
}
},
{
"range": {
"open_date": {
"lt": "2013-07-16"
}
}
}
]
}
}
},
"sort": [
{
"open_date": "desc"
}
]
}
However, the results that come back are not being sorted by "open_date". If I remove the filter:
{
"query": {
"bool": {
"should": [
{
"prefix": {
"name": "foobar"
}
},
{
"query_string": {
"query": "foobar"
}
},
{
"match": {
"name": {
"query": "foobar"
}
}
}
],
"minimum_number_should_match": 1
}
},
"sort": [
{
"open_date": "desc"
}
]
}
... the results come back as expected.
Any ideas?
I'm not sure about the Tire code, but the JSON does not correctly construct a filtered query. My guess is that this overflows and causes the sort element to also not be correctly parsed.
A filtered query should be constructed like this (see http://www.elasticsearch.org/guide/reference/query-dsl/filtered-query/ ):
{
"query": {
"filtered": { // Note: this contains both query and filter
"query": {
"bool": {
"should": [
{
"prefix": {
"name": "foobar"
}
},
{
"query_string": {
"query": "foobar"
}
},
{
"match": {
"name": {
"query": "foobar"
}
}
}
],
"minimum_number_should_match": 1
}
},
"filter": {
"and": [
{
"term": {
"searchable": true
}
},
{
"range": {
"open_date": {
"lt": "2013-07-16"
}
}
}
]
}
}
},
"sort": [
{
"open_date": "desc"
}
]
}
Cheers,
Boaz

Resources