Determining How a Document Was Matched in Elasticsearch - elasticsearch

I would like to make an or search between two different condition trees-
{
"query": {
"bool": {
"should": [
{ "bool": { ... } },
{ "bool": { ... } }
]
}
}
}
And it would be helpful to know of the found documents, which of the two conditions (or both) were matched that resulted in this document match.
Is this possible?

You can use the explain parameter to show how the score was computed. This shows the score for each hit, so it will give the fields that matched and the score.
{
"explain": true,
"query": {
"bool": {
"should": [
{ "bool": { ... } },
{ "bool": { ... } }
]
}
}
}

Thank you #Tim and #Val. I was looking for named_queries.
{
"query": {
"bool": {
"should": [
{ "bool": { "_name": "x", "must": [ ... ] } },
{ "bool": { "_name": "y", "must": [ ... ] } },
]
}
}
}

Related

Elasticsearch constant_score wrapped inside must does not return expected result

I have the following ES query :
{
"query": {
"bool": {
"should": [
{
"constant_score": {
"boost": 5,
"filter": {
"bool": {
"must": [
{
"ids": {
"values": [
"winnerAthlete-A"
]
}
},
{
"dis_max": {
"queries": [
{
"bool": {
"filter": {
"term": {
"isAthlete": true
}
}
}
},
{
"bool": {
"filter": {
"term": {
"isWinner": true
}
}
}
}
]
}
}
]
}
}
}
},
{
"constant_score": {
"boost": 4,
"filter": {
"bool": {
"must": [
{
"ids": {
"values": [
"winnerAthlete-B"
]
}
},
{
"dis_max": {
"queries": [
{
"bool": {
"filter": {
"term": {
"isAthlete": true
}
}
}
},
{
"bool": {
"filter": {
"term": {
"isWinner": true
}
}
}
}
]
}
}
]
}
}
}
}
]
}
}
}
It does return the result I expect : the 2 documents winnerAthlete-A and winnerAthlete-B, assigning a score of 5.0 to winnerAthlete-A and a score of 4.0 to winnerAthlete-B.
Now, when I turn the should on the third line of the query into a must, the query does not match any document whereas I would expect the exact same result. I can't wrap my head around why. I have tried using the ES _explain keyword to understand why this query doesn't match when using must but it didn't help me.
Any idea why this query rewritten with a must does not return anything whereas the should version does return the expected result ?
Should works like "OR" . It will return a document which matches any of clauses.
Must works like "AND" . Document must satisfy both clauses.
Your query is not returning any result because there is no single document which has ids as winnerAthlete-A as well as winnerAthlete-B

Elasticsearch filter by matching query in all nested documents

I have a problem with filtering elastic documents by nested documents.
In general document has a list of nested assets and each asset have a list of teamIds
Sample cut off document:
{
"assets":[
{
"id":100,
"teams":[
1
]
},
{
"id":101,
"teams":[
4,
3
]
}
]
}
Expected result is to get root document where all assets have at least one matching team
I've tried:
{
"from": 0,
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"nested": {
"path": "assets",
"query": {
"terms": {
"assets.teams": [
1
]
}
}
}
}
]
}
},
{
"bool": {
"must_not": [
{
"nested": {
"path": "assets",
"query": {
"bool": {
"must": [
{
"exists": {
"field": "assets"
}
}
]
}
}
}
}
]
}
}
]
}
}
]
}
},
"size": 999
}
Unfortunately this query return document. In this case I do expect it returns document if query contains ids like [1,3], [1,4] or [1,3,4]
Thanks in advance
To find a document where all nested documents contain any of given terms
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "assets",
"query": {
"bool": {
"must_not": [
{
"terms": {
"assets.teams": [
"1"
]
}
}
]
}
}
}
}
]
}
}
}
````
In the above, nested query returns documents where a nested document does not contain any of given term, then outer must_not excludes those documents.
In other words first find documents where a nested document doesnot contain given term and then exclude those documents.
If you want to include documents where teams field is not present use below
````
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "assets",
"query": {
"bool": {
"must": [
{
"exists": {
"field": "assets.teams"
}
}
],
"must_not": [
{
"terms": {
"assets.teams": [
"1"
]
}
}
]
}
}
}
}
]
}
}
}
````

How do i write a search query that performs multiple tasks in Elasticsearch?

I have read the Elasticsearch documentation. I also took a course. My questions is was how do I write one query to handle all my tasks? I learn by example. The documentation doesn't have many examples. I wrote what I think may be how I accomplish this task but I'm not sure i'm doing this correctly.
The ... is where i would put a match query of some sort
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": {
...
},
"should": {
...
}
}
},
{
"bool": {
"query_string": {
...
}
}
},
{
"bool": {
...
}
},
{
"bool": {
"must": {
...
},
"should": {
...
}
}
}
],
"minimum_should_match": 1
}
}
}
Is this how i would do it?
The bool query contain array of [must, filter, should, mustnot] so you don't have to put another bool on it. Inside each of them you can write another bool query of course.
As you add a minimum_should_match, you right, you have to put it just after the should part. Your query has to look like :
{
"query": {
"bool": {
"should": [
{ "query_string" : ... },
{ "terms" : ... },
{ "bool" : ... },
{ "bool" : {
"must": [
{"query_string": ... },
{"bool": ....}
]
}
}
],
"minimum_should_match": 1
}
}
}
You have a good example here:
https://www.compose.com/articles/elasticsearch-query-time-strategies-and-techniques-for-relevance-part-i/
https://hdmetor.github.io/how-to-combine-queries-in-es/

Elastic Search - OR querying for non matches

I'm having trouble querying in elastic search. I'm searching over a specific set of data defined by the state_id, and then wanting to return all the states which do not have either one of the cities defined by the identifiers below.
The query below returns 18 results with just "city_id_1", and 0 results with "city_id_2". With both though, I return 0 results (since "city_id_2" is on every state record). What I want to do is still return the 18 results, but query over both cities.
I feel like my query should be working, and basically doing a NOT (A or B) style query, equivalent to NOT A and NOT B, but basically the 0 results seems to be overriding the 18.
Is there a way I can change my query to get the results I want, or is this something elasticsearch cannot do?
{
"query": {
"bool": {
"must": [
{ "terms": { "state_id": ["4ca16f80-da79-11e5-9874-64006a4f57cb"]}}
],
"must_not": [
{
"nested": {
"path": "cities",
"query": {
"bool": {
"should": [
{"term": { "cities.identifier": "city_id_1"}},
{"term": { "cities.identifier": "city_id_2"}}
]
}
}
}
}
]
}
},
"size": 10
}
Try this on for size. Elasticsearch is silly. The filter needs to be in each of the nested queries.
{
"query": {
"bool": {
"should": [
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "cities",
"query": {
"term": { "cities.identifier": "city_id_1"}
}
}
}
],
"filter":[
{
"term":{
"state_id":"4ca16f80-da79-11e5-9874-64006a4f57cb"
}
}
]
}
}
},
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "cities",
"query": {
"term": { "cities.identifier": "city_id_2"}
}
}
}
],
"filter":[
{
"term":{
"state_id":"4ca16f80-da79-11e5-9874-64006a4f57cb"
}
}
]
}
}
}
]
}
},
"size": 10
}
If you want NOT A AND NOT B behaviour you need to make a little change
{
"query": {
"bool": {
"must": [
{ "terms": { "state_id": ["4ca16f80-da79-11e5-9874-64006a4f57cb"]}}
],
"must_not": [
{
"nested": {
"path": "cities",
"query": {
"bool": {
"must": [ ====> Use must instead of should
{"term": { "cities.identifier": "city_id_1"}},
{"term": { "cities.identifier": "city_id_2"}}
]
}
}
}
}
]
}
},
"size": 10
}
This will exclude those record which will have both city_id_1 and city_id_2.
As per my understanding, you are looking our for NOT A or NOT B kind of a clause. Please check the query below and see if it fits your requirement
{
"query": {
"bool": {
"must": [
{ "terms": { "state_id": ["4ca16f80-da79-11e5-9874-64006a4f57cb"]}}
],
"should": [
{
"nested": {
"path": "cities",
"query": {
"bool": {
"must_not": [
{"term": { "cities.identifier": "city_id_1"}}
]
}
}
}
},
{
"nested": {
"path": "cities",
"query": {
"bool": {
"must_not": [
{"term": { "cities.identifier": "city_id_2"}}
]
}
}
}
}
],
"minimum_number_should_match": 1
}
},
"size": 10
}

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

Resources