Need Nested sorting elastic search query - elasticsearch

Sample Result : need to sort this (name will always be constant, only value will change)
{
"sampleJson": { "loop1": {
"userId": "1",
"loop2": {
"loop3": [
{
"name": "hindi",
"value": "abc"
},
{
"name": "telugu",
"value": "xyz"
}
]
}
},
"loop1": {
"userId": "2",
"loop2": {
"loop3": [
{
"name": "hindi",
"value": "def"
},
{
"name": "telugu",
"value": "ghi"
}
]
}
},
"loop1": {
"userId": "1",
"loop2": {
"loop3": [
{
"name": "hindi",
"value": "jkl"
},
{
"name": "telugu",
"value": "mno"
}
]
}
}
}
}
After performing elastic Sorting, result should look like below:
{
"sampleJson": {
"loop1": {
"userId": "1",
"loop2": {
"loop3": [
{
"name": "hindi",
"value": "jkl"
},
{
"name": "telugu",
"value": "mno"
}
]
}
},
"loop1": {
"userId": "1",
"loop2": {
"loop3": [
{
"name": "hindi",
"value": "abc"
},
{
"name": "telugu",
"value": "xyz"
}
]
}
}
}
}
below Elastic sorting is not working: not sure what is wrong with this. any help that would be great.
{
"from": 0,
"size": 25,
"query": {
"bool": {
"must": [
{
"match": {
"userId": "1"
}
}
]
}
},
"sort": [
{
"sampleJson.loop1.loop2.loop3.value": {
"order":"asc",
"nested": {
"path": "sampleJson",
"filter": {
"terms" : {
"sampleJson.loop1.loop2.loop3.name": [
"telugu"
] }
}
}
}
}
]
}

Related

How to use multi where condition with elasticsearch

I'm using laravel + elasticsearch.
I have an array like this:
[
{
"title": "product_title",
"stocks": [
{
"country": "EN",
"stock": 0
},
{
"country": "IN",
"stock": 1
}
]
},
{
"title": "product_title_2",
"stocks": [
{
"country": "EN",
"stock": 1
},
{
"country": "IN",
"stock": 0
}
]
}
]
Now I want to find all objects has country equal EN and stock is greater than 1.
updated
my query:
{
"index": "products",
"body": {
"size": 15,
"from": 1,
"sort": [
{
"stock": {
"order": "desc"
}
}
],
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "**",
"type": "best_fields",
"fields": [
"erp_id",
"title_en^2",
"translations.title^2",
"erp.title_en",
"erp.title",
"erp.options.title",
"erp.options.title_en"
],
"analyze_wildcard": true,
"allow_leading_wildcard": true
}
}
],
"filter": [
{
"term": {
"is_active": 1
}
},
{
"term": {
"shops.shop_id": 1
}
}
]
}
},
"aggs": {
"max_price": {
"filter": {
"term": {
"erp.price_lists.currency.abbr": "tmn"
}
},
"aggs": {
"result": {
"max": {
"field": "erp.price_lists.pivot.price_tt"
}
}
}
},
"min_price": {
"filter": {
"term": {
"erp.price_lists.currency.abbr": "tmn"
}
},
"aggs": {
"result": {
"min": {
"field": "erp.price_lists.pivot.price_tt"
}
}
}
}
}
}
}
You can use nested query along with inner_hits to get the object satisfying the requirements
Adding a working example
Index Mapping:
{
"mappings": {
"properties": {
"stocks": {
"type": "nested"
}
}
}
}
Index Data:
{
"title": "product_title_2",
"stocks": [
{
"country": "EN",
"stock": 1
},
{
"country": "IN",
"stock": 0
}
]
}
{
"title": "product_title",
"stocks": [
{
"country": "EN",
"stock": 0
},
{
"country": "IN",
"stock": 1
}
]
}
{
"title": "product_title_3",
"stocks": [
{
"country": "EN",
"stock": 2
},
{
"country": "IN",
"stock": 0
}
]
}
Search Query:
{
"query": {
"nested": {
"path": "stocks",
"query": {
"bool": {
"filter": [
{
"match": {
"stocks.country": "EN"
}
},
{
"range": {
"stocks.stock": {
"gt": 1
}
}
}
]
}
},
"inner_hits":{}
}
}
}
Search Result:
"hits": [
{
"_index": "67294405",
"_type": "_doc",
"_id": "3",
"_score": 0.0,
"_source": {
"title": "product_title_3",
"stocks": [
{
"country": "EN",
"stock": 2
},
{
"country": "IN",
"stock": 0
}
]
},
"inner_hits": {
"stocks": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.0,
"hits": [
{
"_index": "67294405",
"_type": "_doc",
"_id": "3",
"_nested": {
"field": "stocks",
"offset": 0
},
"_score": 0.0,
"_source": {
"country": "EN",
"stock": 2
}
}
]
}
}
}
}
]

Nested filter returns 0 doc_count

For this index and sample data:
PUT job_offers
{
"mappings": {
"properties": {
"location": {
"properties": {
"slug": {
"type": "keyword"
},
"name": {
"type": "keyword"
}
},
"type": "nested"
},
"experience": {
"properties": {
"slug": {
"type": "keyword"
},
"name": {
"type": "keyword"
}
},
"type": "nested"
}
}
}
}
POST job_offers/_doc
{
"title": "Junior Ruby on Rails Developer",
"location": [
{
"slug": "new-york",
"name": "New York"
},
{
"slug": "atlanta",
"name": "Atlanta"
},
{
"slug": "remote",
"name": "Remote"
}
],
"experience": [
{
"slug": "junior",
"name": "Junior"
}
]
}
POST job_offers/_doc
{
"title": "Ruby on Rails Developer",
"location": [
{
"slug": "chicago",
"name": "Chicago"
},
{
"slug": "atlanta",
"name": "Atlanta"
}
],
"experience": [
{
"slug": "senior",
"name": "Senior"
}
]
}
I try to run filter on experience.slug:
GET job_offers/_search
{
"query": {
"nested": {
"path": "location",
"query": {
"terms": {
"location.slug": [
"remote",
"new-york"
]
}
}
}
},
"aggs": {
"filtered_job_offers": {
"global": {},
"aggs": {
"filtered_location": {
"filter": {
"bool": {
"must": [
{
"terms": {
"experience.slug": [
"junior"
]
}
}
]
}
}
}
}
}
}
}
Response for this:
"aggregations" : {
"filtered_job_offers" : {
"doc_count" : 2,
"filtered_location" : {
"doc_count" : 0
}
}
}
Why do I get doc_count: 0 for filtered_location instead of 1? How can I make it work?
You were pretty close! Gotta use a nested query in the aggregations:
...
"aggs": {
"filtered_job_offers": {
"global": {},
"aggs": {
"filtered_location": {
"filter": {
"bool": {
"must": [
{
"nested": { <-----
"path": "experience",
"query": {
"terms": {
"experience.slug": [
"junior"
]
}
}
}
}
]
}
}
}
}
}
}

Nested object retrieval in ElasticSearch query

I'm new in ElasticSearch and I have a few questions regarding nested object retrieval when a specific condition is matched.
I have a tree-like structure as follow:
{
"id": 4,
"sora": [
{
"pContext": {
"context": {
"sT": "D3",
"uT": "ST"
},
"entities": [
{
"name": "premium",
"bName": "premium",
"fT": "site",
"eT": "F_P",
"children": [
{
"name": "capa",
"bName": "capa",
"fT": "site",
"eT": "FFT",
"children": []
},
{
"name": "code",
"bName": "Codes",
"fT": "site",
"eT": "FFT",
"children": []
},
{
"name": "selection A",
"fT": "site",
"eT": "SELECTION_A",
"children": [
{
"name": "A1",
"fT": "site",
"eT": "ADD",
"children": []
},
{
"name": "A2",
"fT": "site",
"eT": "ADD",
"children": []
}
]
}
]
}
]
}
},
{
"pContext": {
"context": {
"sT": "D2",
"uT": "ST"
},
"entities": [
{
"name": "112",
"bName": "112",
"eT": "D_TYPE",
"children": []
}
]
}
}
]
}
My structure can have more levels.
I have many documents as described above. In order to filter my document I can use the simple query sintax:
{
"_source": {
"excludes": [
"*.context"
]
},
"query": {
"bool": {
"must": [
{
"match": {
"sora.pContext.context.sT": "D3"
},
"match": {
"sora.pContext.entities.name": "premium"
},
"match": {
"sora.pContext.entities.fT": "site"
}
}
]
}
}
}
What I would like to know is, how can I get the nested object that
matches my query and their children. I need the object that matched
the must inclusive filter. Is that possible?
How can I search for a field without specifing the path?
Thanks
# EDIT
My mapping:
{
"mappings": {
"abc": {
"properties": {
"id": {
"type": "integer"
},
"sora": {
"type": "nested",
"properties": {
"pContext": {
"type": "nested",
"properties": {
"context": {
"type": "nested",
"properties": {
"sT": {
"type": "text"
},
"uT": {
"type": "text"
}
}
},
"entities": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"bName": {
"type": "text"
},
"fT": {
"type": "text"
},
"eT": {
"type": "text"
},
"children": {
"type": "object"
}
}
}
}
}
}
}
}
}
}
}
Yes you can get the matching objects by using inner_hits along with nested query and not the one you added to the question.
Your query will look as below:
{
"_source": {
"excludes": [
"*.context"
]
},
"query": {
"bool": {
"filter": [
{
"nested": {
"inner_hits": {},
"path": "sora.pContext",
"query": {
"bool": {
"must": [
{
"nested": {
"path": "sora.pContext.context",
"query": {
"bool": {
"must": [
{
"match": {
"sora.pContext.context.sT": "D3"
}
}
]
}
}
}
},
{
"nested": {
"path": "sora.pContext.entities",
"query": {
"bool": {
"must": [
{
"match": {
"sora.pContext.entities.name": "premium"
}
},
{
"match": {
"sora.pContext.entities.fT": "site"
}
}
]
}
}
}
}
]
}
}
}
}
]
}
}
}
I have added link to inner_hits documentation where you can understand how the results will look like.
Well, if someone else is facing the same issue my solution was added all child in the same path/level as the parent but keep the mapping with parent and their children. With that, I'm able to search and retrieve the parts of the parent as wanted.

How to get by ids and filter nested data to leave only objects filtered by category?

How to get by ids and filter notes to leave only given category?
Data:
POST c1_2/Blog/1
{
"post": {
"notes": {
"main": [
{
"message": "blablabla",
"category": "test"
},
{
"message": "blablabla",
"category": "other"
}
],
"cart": [
{
"message": "blablabla",
"category": "test"
},
{
"message": "blablabla",
"category": "other"
}
]
}
}
}
POST c1_2/Blog/2
{
"post": {
"notes": {
"main": [
{
"message": "blablabla",
"category": "second"
},
{
"message": "blablabla",
"category": "third"
}
],
"cart": [
{
"message": "blablabla",
"category": "test"
},
{
"message": "blablabla",
"category": "other"
}
]
}
}
}
Search:
POST c1_2/Blog/_search
{
"query": {
"bool": {
"must": [
{
"ids": {
"values": [
1,
2,
3
]
}
},
{
"terms": {
"post.notes.main.category": [
"test"
]
}
}
]
}
}
}
Current results, objects in notes main/cart aren't filtered by category:
{
"took": 9,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.0122644,
"hits": [
{
"_index": "c1_2",
"_type": "Blog",
"_id": "1",
"_score": 1.0122644,
"_source": {
"post": {
"notes": {
"main": [
{
"message": "blablabla",
"category": "test"
},
{
"message": "blablabla",
"category": "other"
}
],
"cart": [
{
"message": "blablabla",
"category": "test"
},
{
"message": "blablabla",
"category": "other"
}
]
}
}
}
}
]
}
}
Desired effect:
"notes": {
"main": [
{
"message": "blablabla",
"category": "test"
}
],
"cart": [
{
"message": "blablabla",
"category": "test"
}
]
}
In my real app query is embedded in "filtered" and "filter", if I will put query above instead filter "ids" like in example below, then will it return the same data?
POST c1_2/Blog/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"ids": {
"values": [
"1",
"2"
]
}
}
}
}
}
Mapping:
{
"posts": {
"mappings": {
"posts": {
"dynamic_templates": [{
"blog": {
"mapping": {
"index": "analyzed"
},
"path_match": "blog.*",
"path_unmatch": "*.medias.*"
}
}, {
"ids": {
"mapping": {
"index": "not_analyzed",
"type": "string"
},
"match": "_id|base_id",
"match_pattern": "regex"
}
}],
"_all": {
"enabled": false
},
"properties": {
"query": {
"properties": {
"filtered": {
"properties": {
"filter": {
"properties": {
"ids": {
"properties": {
"values": {
"type": "string"
}
}
}
}
},
"query": {
"properties": {
"match_all": {
"type": "object"
}
}
}
}
},
"match_all": {
"type": "object"
}
}
},
"source": {
"dynamic": "true",
"properties": {
"post": {
"dynamic": "true",
"properties": {
"_id": {
"type": "string",
"index": "not_analyzed"
},
"base_id": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
},
"blog": {
"properties": {
"post": {
"properties": {
"_id": {
"type": "string"
},
"notes": {
"properties": {
"main": {
"properties": {
"id": {
"type": "string"
},
"message": {
"type": "string"
},
"category": {
"type": "string"
}
}
},
"cart": {
"properties": {
"id": {
"type": "string"
},
"message": {
"type": "string"
},
"category": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": {
"terms": {
"_id": [1, 2]
}
},
"must_not": {
"terms": {
"post.notes.main.category": [
"other"
]
}
}
}
}
}
}
}

How to narrow down the current aggregation context to a specific scope within set of documents returned from Filter Aggregation?

I have a nested object mapping, the sample data:
{
"_index": "simpleindex",
"_type": "games",
"_id": "AU_eC-Uzt6KxlUliF68N",
"_score": 1,
"_source": {
"continents": [
{
"name": "Asia",
"countries": [
{
"name": "India",
"states": [
{
"name": "TN",
"game": "soccor",
"wins": 1
}
]
},
{
"name": "India",
"states": [
{
"name": "KA",
"game": "soccor",
"wins": 1
}
]
}
]
}
]
}
},
{
"_index": "simpleindex",
"_type": "games",
"_id": "AU_eCf5dt6KxlUliF637",
"_score": 1,
"_source": {
"continents": [
{
"name": "Asia",
"countries": [
{
"name": "India",
"states": [
{
"name": "TN",
"game": "soccor",
"wins": 1
}
]
}
]
}
]
}
},
{
"_index": "simpleindex",
"_type": "games",
"_id": "AU_eDIdXt6KxlUliF69i",
"_score": 1,
"_source": {
"continents": [
{
"name": "Asia",
"countries": [
{
"name": "India",
"states": [
{
"name": "TN",
"game": "soccor",
"wins": 1
}
]
},
{
"name": "India",
"states": [
{
"name": "KA",
"game": "soccor",
"wins": 1
}
]
},
{
"name": "Pak",
"states": [
{
"name": "NA",
"game": "soccor",
"wins": 1
}
]
}
]
}
]
}
}
Here is my Filtered Aggregation that returns documents that matches the filter criteria (i.e. continent should be 'Asia' AND country should be 'India'):
{
"aggs": {
"DocumentSet": {
"filter": {
"and": {
"filters": [
{
"nested": {
"path": "continents",
"query": {
"match": {
"continents.name": "asia"
}
}
}
},
{
"nested": {
"path": "continents.countries",
"query": {
"match": {
"continents.countries.name": "india"
}
}
}
}
]
}
},
"aggs": {
"continents": {
"nested": {
"path": "continents"
},
"aggs": {
"countries": {
"nested": {
"path": "continents.countries"
},
"aggs": {
"states": {
"nested": {
"path": "continents.countries.states"
},
"aggs": {
"count": {
"value_count": {
"field": "continents.countries.states.wins"
}
}
}
}
}
}
}
}
}
}}}
And here is the result (copy pasted only the aggregation here):
"aggregations": {
"DocumentSet": {
"doc_count": 3,
"continents": {
"doc_count": 3,
"countries": {
"doc_count": 6,
"states": {
"doc_count": 6,
"count": {
"value": 6
}
}
}
}
}
}
My intention is to get "wins" only from continents.name=asia AND countries.name=india. The filter works as expected but I need to narrow down the aggregation scope only to countries.name=india; essentially another level of scope on the docs returned by Filter aggregation so that leaf aggregation count is 5 instead of 6.
Try this aggregation:
{
"aggs": {
"continents": {
"nested": {
"path": "continents"
},
"aggs": {
"asia_continent": {
"filter": {
"query": {
"match": {
"continents.name": "asia"
}
}
},
"aggs": {
"countries": {
"nested": {
"path": "continents.countries"
},
"aggs": {
"india_country": {
"filter": {
"query": {
"match": {
"continents.countries.name": "india"
}
}
},
"aggs": {
"states": {
"nested": {
"path": "continents.countries.states"
},
"aggs": {
"count": {
"value_count": {
"field": "continents.countries.states.wins"
}
}
}
}
}
}
}
}
}
}
}
}
}
}

Resources