Elastic query combining should (boolean OR) with retrieval of nested documents - elasticsearch

I have an Elastic index with nested documents. I am trying to retrieve multiple documents by ids along with their nested documents. Retrieving the documents themselves is simple enough with a Should query, but where and how would I include the nested doc query in this?
Boolean "Should" query:
GET myIndex/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"id": "123"
}
},
{
"term": {
"id": "456"
}
},
{
"term": {
"id": "789"
}
}
]
}
}
}
Query to retrieve nested docs:
"nested": {
"path": "myNestedDocs",
"query": {
"match_all": {}
}
It is not possible to add the nested query to each term query, because this gives a parsing exception: "[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]"
Also, it is not possible to add the nested doc query on the same level as the term queries, because then it would be treated as just another OR clause and simply retrieve all docs from the index.
Any ideas? Thanks!

As per my understanding, you want to match any one id from list and retrive nested document. If my understanding correct then You need to combined both the query to must clause like below:
{
"query": {
"bool": {
"must": [
{
"terms": {
"id": [
"123",
"456",
"789"
]
}
},
{
"nested": {
"path": "myNestedDocs",
"query": {
"match_all": {}
}
}
}
]
}
}
}

Related

how to make match query on array field more accurate

example:
here is a document:
{
"_source": {
"name": [
"beef soup",
"chicken rice"
]
}
}
it can be recalled by below query
{
"match": {
"name": {
"query": "soup chicken noodle",
"minimum_should_match": "67%"
}
}
}
but I only want it to be recalled by keyword hot beef soup or rice chicken hainan, is there any way except nested or span query to do this, thanks.
my es query is complex, anyone know how to rewrite it by span query
{
"query": {
"bool": {
"filter": [
...
],
"must": {
"dis_max": {
"queries": [
{
"match": {
"array_field_3": {
"boost": 2,
"minimum_should_match": "67%",
"query": "keyword aa bb"
}
}
},
......
{
"nested": {
"path": "path_1",
"query": {
"must": {
"match": {
"array_field_6": {
......
"query": "keyword aa bb"
}
}
}
}
}
}
}
],
"tie_breaker": 0.15
}
}
}
}
}
You can use match_phrase but it will only work for entire phrase. if you want to do only keyword match on each element of array then it is not possible without nested or span as mentioned in document.
Arrays of objects do not work as you would expect: you cannot query
each object independently of the other objects in the array. If you
need to be able to do this then you should use the nested data type
instead of the object data type.
When you get a document back from Elasticsearch, any arrays will be in the same order as when you indexed the document. The _source field that you get back contains exactly the same JSON document that you indexed.
However, arrays are indexed — made searchable — as multi-value fields, which are unordered. At search time you can’t refer to “the first element” or “the last element”.
Please try match_phrase query:
POST index1/_search
{
"query": {
"match_phrase": {
"text": {
"query": "chicken soup"
}
}
}
}

Elasticsearch search query: nested query with OR-gates & AND-gates

I have docs as follow:
{
"name": "...",
"country": "...",
}
I need to find. either one of the following criteria:
name=John AND country=US
name=Andy AND country=UK
How should be write this nested query?
Assuming the default fields mapping is defined, you can use boolean queries as follows:
{
"query": {
"bool": {
"should": [
{
"bool": {
"filter": [
{
"term": {
"name.keyword": "John"
}
},
{
"term": {
"country.keyword": "US"
}
}
]
}
},
{
"bool": {
"filter": [
{
"term": {
"name.keyword": "Andy"
}
},
{
"term": {
"country.keyword": "UK"
}
}
]
}
}
]
}
}
}
You should use must instead of filter if you want the query to contribute to the score.
must
The clause (query) must appear in matching documents and will
contribute to the score.
filter
The clause (query) must appear in matching documents. However unlike
must the score of the query will be ignored. Filter clauses are
executed in filter context, meaning that scoring is ignored and
clauses are considered for caching.

Nested queries in Elastic search which should apply on all objects in nested array

Hi I have this document in ES with nested type:
{
"id": "92210f7f-b8a4-4d55-877d-8708154aa004",
"additionalData": {
"devices_nested": [
{
"version_string": "1"
},
{
"os_string": "Windows",
"version_string": "3"
},
{
"os_string": "Centos"
}
]
}
I want to do query that additionalData.devices_nested does not contain any element where os_string property does not exist that means I want to avoid such documents where some entries could have or not os_string property. Here is my query:
{
"query": {
"nested": {
"query": {
"bool": {
"must": {
"exists": {
"field": "additionalData.devices_nested.os_string"
}
}
}
},
"path": "additionalData.devices_nested"
}
}
}
But I always get the example document as result because at least one element satisfies query that there is os_string property.
Is it possible to make query which will return document where all elements in devices_nested has os_string property?
Is it possible to make query which will return document where all elements in devices_nested has os_string property?
Yes, it is posible. Instead of must exist, you have to use must_not missing approach.
In following query, the bool condition inside nested will match all documents that do not have os_string field in at least one of the nested objects, and then, the outside must_not query will exclude these documents. As a result, you'll get only documents that include os_string field in all nested objects:
{
"query": {
"bool": {
"must_not": {
"nested": {
"query": {
"bool": {
"must_not": {
"exists": {
"field": "additionalData.devices_nested.os_string"
}
}
}
},
"path": "additionalData.devices_nested"
}
}
}
}
}

How to display "ALL" the nested documents in an object in separate rows from elasticsearch?

I have a nested object in the following form:
{
"name": "Multi G. Enre",
"books": [
{
"name": "Guns and lasers",
"genre": "scifi",
"publisher": "orbit"
},
{
"name": "Dead in the night",
"genre": "thriller",
"publisher": "penguin"
}
]
}
I tried the following JSON query for the above document:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "books",
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"and": [
{
"term": {
"books.publisher": "penguin"
}
},
{
"term": {
"books.genre": "thriller"
}
}
]
}
}
}
}
}
}
}
}
So,I would like to see the second nested document i.e. "Dead in the night" as the result but, for anything I search only the first document i.e. "Guns and lasers" is displayed in the table in elasticsearch head plugin.
So, is there any way I can display the nested documents separately based on the search query and not just the first document?
I'm new to elasticsearch,so would appreciate any type of responses. THANKYOU!
You need to use inner_hits in your query.
Moreover, if you want to only retrieve the matching nested document and nothing else, you can add "_source":["books"] to your query and only the matching nested books will be returned, nothing else.
UPDATE
Sorry, I misunderstood your comment. You can add "_source": false and the top-level document will not be returned. Only the nested matching document.

Elasticsearch function_score with nested_objects

I have a problem with a query.I used a query for boosting documents with no nested_objects. Now i use nested_objects and changed the query to use a nested filter but nothing is boosted.
I get the documents i expected but with no _score changes.
Am i doing something wrong ??
GET index/type/_search
{
"query": {
"function_score": {
"filter": {
"bool": {
"must": [
{
"term": {
"parent.child": "test"
}
}
]
}
},
"functions": [
{
"boost_factor": "100",
"filter": {
"nested": {
"path": "parent",
"filter": {
"bool": {
"must": [
{
"term": {
"child": "test"
}
}
]
}
}
}
}
}
],
"score_mode": "sum"
}
},
"sort": "_score",
"from": 0,
"size": 320
}
EDIT:
Could it be caused by
nested filter
A nested filter behaves much like a nested query, except that it
doesn’t accept the score_mode parameter. It can only be used in
“filter context” — such as inside a filtered query —  and it behaves
like any other filter: it includes or excludes, but it doesn’t score.
While the results of the nested filter itself are not cached, the
usual caching rules apply to the filter inside the nested filter.
http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/nested-query.html
As the documentation says:
nested filter
A nested filter behaves much like a nested query, except that it doesn’t accept the score_mode parameter. It can only be used in “filter context” — such as inside a filtered query —  and it behaves like any other filter: it includes or excludes, but it doesn’t score.
While the results of the nested filter itself are not cached, the usual caching rules apply to the filter inside the nested filter.
http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/nested-query.html
I get the feeling your JSON should look closer this (maybe not exactly though, I havent tested it).
{
"query": {
"function_score": {
"query": {
"nested": {
"path": "parent",
"query": {
"bool": {
"must": [
{
"term": {
"parent.child": "test"
}
}
]
}
}
}
},
"functions": [
{
"boost_factor": "100"
}
],
"score_mode": "sum"
}
},
"sort": "_score",
"from": 0,
"size": 320
}
Specifically, you dont want to filter the boost_factor, you just want to boost this function_score by 100. The actual nested query though goes in the query section of the function_score, and the functions section just contains the boost_factor. I think.

Resources