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

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

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

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.

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!

How to check how many documents do not exist out of a list in elasticsearch

What will be the query to retrieve the number of documents not found in a query
This is my Query
$params['body']['query']["bool"]["filter"]["terms"]["feild"] = (list);
I want to retrieve the documents not found from the list.
If my List has (A,B,C). i just need to know that C is not indexed. I don't Need A,B,D,E,F or all of the remaining documents in index.
You can use must_not clause to achieve the negation of your query as shown below:
GET my-index/_search
{
"query": {
"constant_score": {
"filter": {
"bool": {
"must_not": {
"terms": {
"field": [
"value-1", "value-2"
]
}
}
}
}
}
}
}
must_not with aggregation will give more details about that field values which you are not expecting :-
{
"_source":false,
"query": {
"bool": {
"must_not": [
{"term": {"aFieldName": "aFieldValue"}}
]
}
},
"aggregations": {
"byLocation": {
"terms": {
"field": "aFieldName"
}
}
}
}

ElasticSearch NEST - Search on multiple types but apply filter on selected Type alone

I am looking to achieve a single query for search and filtering. But as expected when i applied filtering, the filter condition applied to all types so i got only the result of those document who have that filtered property and value .
For example,
Here i searched in 3 types (Product,Category,Manufacturer)
GET /my-index/Product,Category,Manufacturer/_search
{
"query": {
"filtered": {
"query": {...}, //--> Search a word which present in all types
"filter": {
"term": {
"ProductField": "VALUE"
}
}
}
}
}
Here i got only the result of Product type because Product type only contains field like 'ProductField' and has value as 'VALUE'.
What i am expecting is, with a single query, fetch all types results(Product,Category,Manufacturer), that satisfying the search query and apply filtering only on Product.
So my doubt is
Is there any way in Elastic search to apply filtering on specific type
search results alone than applying to all types?
Yes, you can use the type query to achieve exactly that. In the filter, we have a bool/should clause that selects either Category or Manufacturer without any other conditions, or Product documents having ProductField: VALUE:
POST /my-index/Product,Category,Manufacturer/_search
{
"query": {
"filtered": {
"query": {},
"filter": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"type": {
"value": "Category"
}
},
{
"type": {
"value": "Manufacturer"
}
},
{
"bool": {
"must": [
{
"type": {
"value": "Product"
}
},
{
"term": {
"ProductField": "VALUE"
}
}
]
}
}
]
}
}
}
}
}

Resources