Elasticsearch: inner_hits does not work for nested queries (nested twice) - elasticsearch

I'm using ES v1.5.2 (so inner_hits is present and does work correctly for filters) and I have deeply nested documents in elasticsearch with nested paths :
members
members.members
This means that in the mapping (https://gist.github.com/frickm/834a4ff8f952cb86ec02) these two fields are declared as nested. I also have a working query (which essentially is a doubly nested filter on un-analyzed strings) which is shown below and which does work perfectly fine (my actual use-case has an even deeper nesting).
I have two inner_hits clauses in the query: the outer work works
The problem is that the "inner" inner_hits does not work: for the first inner_hits clause we obtain the "real" inner-hits for the members field; but for the second inner_hits clause I get following result for members.members field, which is just wrong (the hits cannot be empty, since then the entire document wouldn't be a hit):
"members.members": {
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
Query:
POST nia/condition/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "members",
"filter": {
"bool": {
"must": [
{
"nested": {
"path": "members.members",
"filter": {
"bool": {
"must": [
{
"term": {
"members.members.findingRef.name": "ImpairedSenseOfTouch"
}
}
]
}
},
"inner_hits": {}
}
}
]
}
},
"inner_hits": {}
}
}
}
}
}
Remark: Replacing the bool filter with direct term filter does not help either (and it shouldn't matter since entire "sub-documents' are supposed to be given back).

Related

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

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": {}
}
}
}
]
}
}
}

How to return multiple inner hits in multiple nested sub-queries for the same path?

When I have multiple nested sub-queries for the same path, it seems the result will only include the inner hits result of the last nested sub-query. Is there a way to return all of the inner hits results for the multiple nested sub-queries?
e.g.
{
"query": {
"bool: {
"must": [{
"nested": {
"query": {...},
"path": "path_a",
"inner_hits": {}
}
},{
"nested": {
"query": {...},
"path": "path_a",
"inner_hits": {}
}
}]
}
}
}
If you add a unique name to your inner_hits, then the result will basically contain a map of your inner hits as you're expecting.
Note: It seems that sometimes the inner hits contains extra query names (from the other nested queries) in the matched_queries, so it may need some post-processing
For the same path one needs to specify the nested path before its sub-queries.
Below is an example of searching, either via the match or the range, in the same nested path. You could modify the search according to your needs.
GET index/_search
{
"query": {
"nested": {
"path": “path.subpath”,
"query": {
"bool": {
"must": [
{ "match": { “path.subpath.match1”: “valueMatch” }},
{ "range" : { “path.subpath.range1” : {"gte": “rangeMatch” } }
}
]
}
}
}
}
}
I hope this helps!

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