How do I query an Elasticsearch nested document within an inner object? - elasticsearch

I'm trying to filter on a field within a nested document in an Elasticsearch query (ES 5.6.2). The nested document is itself a field within an inner object of the main document. The mapping looks like this:
{
"mappings": {
"container": {
"properties": {
"host": {
"properties": {
"tags_nested": {
"type": "nested",
"properties": {
"tag_key": {
"type": "keyword"
},
"tag_val": {
"type": "keyword"
}
}
}
}
}
}
}
}
}
I want to filter on host.tags_nested.tag_keys, but I can't figure out the right syntax to access the nested tags_nested document within the host inner object. I tried the following query, which doesn't return any results, when I know there are some that should match:
{
"query": {
"nested": {
"path": "host.tags_nested",
"query": {
"bool": {
"filter": [
{
"term": {
"host.tags_nested.tag_key": "example_key"
}
}
]
}
}
}
}
}
According to the ES docs, you can do a nested query to query within a nested doc, by passing a path which corresponds to the field name of the nested doc. But this seems not to work when the path is within an inner object and needs to be accessed using dot notation.
Any ideas?

Try this. Term Query searches for exact words which we specify. So, for that use fieldname.keyword because keyword stores exact text as we index them.
{
"query": {
"nested": {
"path": "host.tags_nested",
"query": {
"bool": {
"filter": [
{
"term": {
"host.tags_nested.tag_key.keyword": "example_key"
}
}
]
}
}
}
}
}

Related

Nested Term ElasticSearch 7 problem / Elastica Don't work - BEGINNER

I'm trying to get exact search with slug in nested element in ElasticSearch but it seems like that it doesn't work.
So when i'm trying a simple nested match with "my-slug" i get result with "my" and "slug", Normal...
GET my-index/_search
{
"query": {
"nested": {
"path": "productTranslation",
"query": {
"bool": {
"must": [
{
"match": {
"productTranslation.slug": "my-slug"
}
}
]
}
}
}
}
}
But i have no result when i'm trying with term or filter search.
GET my-index/_search
{
"query": {
"nested": {
"path": "productTranslation",
"query": {
"bool": {
"filter": [
{
"term": {
"productTranslation.slug": "my-slug"
}
}
]
}
}
}
}
}
Any idea where the error lies??
Thank's for help.
Term query doesn't perform any analysis on the term. So, in term query you need to have an exact match.
If you have not explicitly defined any mapping then you need to add .keyword to the productTranslation.slug field. This uses the keyword analyzer instead of the standard analyzer (notice the ".keyword" after productTranslation.slug field).
{
"query": {
"nested": {
"path": "productTranslation",
"query": {
"bool": {
"filter": [
{
"term": {
"productTranslation.slug.keyword": "my-slug" // note this
}
}
]
}
}
}
}
}
OR you can change the data type of the productTranslation.slug field to keyword type
{
"mappings": {
"properties": {
"productTranslation": {
"properties": {
"slug": {
"type": "keyword"
}
}
}
}
}
}

How do I refer to multiple nesting levels in an Elastic Search's Filter Aggregation?

Let's call my root level foo and my child level events. I want to aggregate on the events level but with a filter that EITHER the event has color "orange" OR the parent foo has customerId "35".
So, I want to have a filter aggregation that's inside a nested aggregation. In this filter's query clause, I have one child that refers to a field on foo and the other refers to a field on events. However, that first child has no way to actually reference the parent like that! I can't use a reverse_nested aggregation because I can't put one of those as a child of a compound query, and I can't filter before nesting because I'd lose the OR semantics that way. How do I reference the field on foo?
Concrete example if it helps. Mapping:
{
"foo": {
"properties": {
"customer_id": { "type": "long" },
"events": {
"type": "nested",
"properties": {
"color": { "type": "keyword" },
"coord_y": { "type": "double" }
}
}
}
}
}
(update for clarity: that's an index named foo with the root mapping named foo)
The query I want to be able to make:
{
"aggs": {
"OP0_nest": {
"nested": { "path": "events" },
"aggs": {
"OP0_custom_filter": {
"filter": {
"bool": {
"should": [
{ "term": { "events.color": "orange" } },
{ "term": { "customer_id": 35 } }
]
}
},
"aggs": {
"OP0_op": {
"avg": { "field": "events.coord_y" }
}
}
}
}
}
}
}
Of course, this does not work, because the child of the should clause containing customer_id does not work. That term query is always false because customer_id can't be accessed inside the nested aggregation.
Thanks in advance!
Since the fields you want to apply filter on are at different levels you need to make query for each level separately and place them in should clause of bool query which becomes the filter for our filter aggregation. In this aggregation we then add a nested aggregation to get the avg of coord_y.
The aggregation will be (UPDATED: since foo is index name removed foo from field names):
{
"aggs": {
"OP0_custom_filter": {
"filter": {
"bool": {
"should": [
{
"term": {
"customer_id": 35
}
},
{
"nested": {
"path": "events",
"query": {
"term": {
"events.color": "orange"
}
}
}
}
]
}
},
"aggs": {
"OP0_op": {
"nested": {
"path": "events"
},
"aggs": {
"OP0_op_avg": {
"avg": {
"field": "events.coord_y"
}
}
}
}
}
}
}
}

Multiple (AND) queries for a nested index structure in Elasticsearch

I have an index with the below mapping
{
"mappings": {
"xxxxx": {
"properties": {
"ID": {
"type": "text"
},
"pairs": {
"type": "nested"
},
"xxxxx": {
"type": "text"
}
}
}
}
}
the pairs field is essentially an array of objects - each object has a unique ID associated with it
What i'm trying to do is to get only one object from the pairs field for updates. To that extent , i've tried this
GET /sample/_search/?size=1000
{
"query": {
"bool": {
"must": [
{
"match": {
"ID": "2rXdCf5OM9g1ebPNFdZNqW"
}
},
{
"match": {
"pairs.id": "c1vNGnnQLuk"
}
}
]
}
},
"_source": "pairs"
}
but this just returns an empty object despite them being valid IDs. If i remove the pairs.id rule - i get the entire array of objects .
What do i need to add/edit to ensure that i can query via both IDS (original and nested)
Since pairs is of nested type, you need to use a nested query. Also you might probably want to leverage nested inner-hits as well:
GET /sample/_search/?size=1000
{
"query": {
"bool": {
"must": [
{
"match": {
"ID": "2rXdCf5OM9g1ebPNFdZNqW"
}
},
{
"nested": {
"path": "pairs",
"query": {
"match": {
"pairs.id": "c1vNGnnQLuk"
}
},
"inner_hits": {}
}
}
]
}
},
"_source": false
}

Elasticsearch nested object query_string

I have question about query_string query in ElasticSearch. I want create fulltext search over all types and fields in index. Is query_string string performed against nested objects ? For example I have this mapping
{
"my_index": {
"mappings": {
"my_type": {
"properties": {
"group": {
"type": "string"
},
"user": {
"type": "nested",
"properties": {
"first": {
"type": "string"
},
"last": {
"type": "string"
}
}
}
}
}
}
}
}
And the query
GET /my_index/_search
{
"query": {
"query_string" : {
"query" : "paul"
}
}
}
So when I call the query, will ES search across all fields including nested or only in my_type object and for nested search I will have to use nested query ?
You cannot reference nested fields from a query_string at the root. i.e. this won't work:
{
"query": {
"query_string": {
"query": "myNestedObj.myTextField:food"
}
}
}
To search in specific nested fields, you must use the nested clause:
{
"query": {
"nested": {
"path": "myNestedObj",
"query": {
"query_string": {
"query": "myNestedObj.myTextField:food"
}
}
}
}
}
}
However, I've found that the pseudo-field "_all" does include nested fields, so this query would find documents containing 'food' in myNestedObj.myTextField (as well as anywhere else)
{
"query": {
"query_string": {
"query": "_all:food"
}
}
}
Try:
GET my_index/_search?q=paul

elasticsearch - find document by exactly matching a nested object

I have documents that contain multiple role/right definitions as an array of nested objects:
{
...
'roleRights': [
{'roleId':1, 'right':1},
{'roleId':2, 'right':1},
{'roleId':3, 'right':2},
]
}
I am trying to filter out document with specific roleRights, but my query seems to mix up combinations. Here is my filterQuery as "pseudoCode"
boolFilter > must > termQuery >roleRights.roleId: 1
boolFilter > must > termQuery >roleRights.type: 2
The above should only return
documents that have role 1 assigned with right 2.
But it looks like i get
all document that have role 1 assigned disregarding the right
and all documents that have right 2 assigned disregarding the role.
Any hints?
You need to map roleRights as nested (see a good explanation here), like below:
PUT your_index
{
"mappings": {
"your_type": {
"properties": {
"roleRights": {
"type": "nested",
"properties": {
"roleId": { "type": "integer" },
"right": { "type": "integer" }
}
}
}
}
}
}
Make sure to delete your index first, recreate it and re-populate it.
Then you'll be able to make your query like this:
POST your_index/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "roleRights",
"query": {
"term": { "roleRights.roleId": 1}
}
}
},
{
"nested": {
"path": "roleRights",
"query": {
"term": { "roleRights.type": 2}
}
}
}
]
}
}
}

Resources