I have a "products" index with the nested field mapping. I perform a search query with nested aggregation and term aggregation by nested object's id. How to get "title" and "slug" properties from nested object in buckets?
PUT /products
{
"mappings": {
"properties": {
"categories": {
"type": "nested",
"properties": {
"id": { "type": "long" },
"title": { "type": "text" },
"slug": { "type": "keyword" }
}
}
}
}
}
POST /products/_doc
{
"name": "Acer Aspire 5 Slim Laptop",
"categories": [
{
"id": 1,
"title": "Laptops",
"slug": "/catalog/laptops"
},
{
"id": 2,
"title": "Ultrabooks",
"slug": "/catalog/ultrabooks"
}
]
}
GET /products/_search
{
"query": {
"match": { "name": "acer" }
},
"aggs": {
"categories": {
"nested": {
"path": "categories"
},
"aggs": {
"id": {"terms": {"field": "categories.id"}}
}
}
}
}
That's a great start!! All you need is to add a top_hits sub-aggregation like this:
GET /products/_search
{
"query": {
"match": {
"name": "acer"
}
},
"aggs": {
"categories": {
"nested": {
"path": "categories"
},
"aggs": {
"id": {
"terms": {
"field": "categories.id"
},
"aggs": {
"hits": {
"top_hits": {
"size": 1,
"_source": ["categories.title", "categories.slug"]
}
}
}
}
}
}
}
}
Related
How do I write a query with two search terms which matches nested objects with inner hits highlighted.
Below is the sample usecase:
I have a mapping:
"mappings": {
"properties": {
"grocery_name": {
"type": "text"
},
"items": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"stock": {
"type": "integer"
},
"category": {
"type": "text"
}
}
}
}
}
and the data looks like below
{
"grocery_name": "Elastic Eats",
"items": [
{
"name": "Red banana",
"stock": "12",
"category": "fruit"
},
{
"name": "Cavendish banana",
"stock": "10",
"category": "fruit"
},
{
"name": "peach",
"stock": "10",
"category": "fruit"
},
{
"name": "carrot",
"stock": "9",
"category": "vegetable"
},
{
"name": "broccoli",
"stock": "5",
"category": "vegetable"
}
]
}
here if i want a document which has peach and carrot both in nested docs
i can do search with multiple nested queries like below
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "items",
"query": {
"match_phrase": {
"items.name": {
"query": "carrot"
}
}
}
}
},
{
"nested": {
"path": "items",
"query": {
"match_phrase": {
"items.name": {
"query": "peach"
}
}
}
}
}
]
}
}
}
the above query works perfectly, but if i add inner hits i can't add for both nested queries , if i do i get following error
[inner_hits] already contains an entry for key[items]
i want to get each matched nested object highlighted, as _source highlighting is not supported in elasticsearch is there any way i can do highlighting for each nested object?
You certainly can have multiple inner_hits but they need to be appropriately named:
{
"query": {
"bool": {
"must": [
{
"nested": {
"inner_hits": {
"name": "carrot" <--
},
"path": "items",
"query": {
"match_phrase": {
"items.name": {
"query": "carrot"
}
}
}
}
},
{
"nested": {
"inner_hits": {
"name": "peach" <--
},
"path": "items",
"query": {
"match_phrase": {
"items.name": {
"query": "peach"
}
}
}
}
}
]
}
}
}
You were getting the error b/c if no name is provided, the system will default to the nested path which is items in both of your subqueries.
Is it possible using the Elastic Search _count API and having the following abbreviated ES template to find the count of sponsorships for all the campaigns by brandId?
sponsorshipSets and sponsorships are optional so it can be null.
{
"index_patterns": "campaigns*",
"order": 4,
"version": 4,
"aliases": {
"campaigns": {
}
},
"settings": {
"number_of_shards": 5
},
"mappings": {
"dynamic": "false",
"properties": {
"brandId": {
"type": "keyword"
},
"sponsorshipSets": {
"type": "nested",
"properties": {
"id": {
"type": "keyword"
},
"sponsorships": {
"type": "nested",
"properties": {
"id": {
"type": "keyword"
}
}
}
}
}
}
filter aggregation can be used to fetch docs with certain brand Id. Two Nested aggregations to point to sponsorship and value_count aggregation to get the count.
Query
{
"aggs": {
"selected_brand": {
"filter": {
"term": {
"brandId": "1"
}
}
},
"sponsorshipSets": {
"nested": {
"path": "sponsorshipSets"
},
"aggs": {
"sponsorships": {
"nested": {
"path": "sponsorshipSets.sponsorships"
},
"aggs": {
"count": {
"value_count": {
"field": "sponsorshipSets.sponsorships.id"
}
}
}
}
}
}
}
}
I found a solution without using Aggregations, it seems more accurate from the above and I can use the _count API.
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "sponsorshipSets.sponsorships",
"query": {
"bool": {
"filter": {
"exists": {
"field": "sponsorshipSets.sponsorships"
}
}
}
}
}
},
{
"term": {
"brandId": "b1d28821-3730-4266-8f55-eb69596004fb"
}
}
]
}
}
}
I am new to elasticsearch and don't know a lot about aggregations but I have this ES6 mapping:
{
"mappings": {
"test": {
"properties": {
"id": {
"type": "integer"
}
"countries": {
"type": "nested",
"properties": {
"global_id": {
"type": "keyword"
},
"name": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
},
"areas": {
"type": "nested",
"properties": {
"global_id": {
"type": "keyword"
},
"name": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"parent_global_id": {
"type": "keyword"
}
}
}
}
}
}
}
How can I get all documents grouped by areas which is then grouped by countries. Also the document has to be returned in full, not just the nested document. Is this even possible ?
1) Aggregation _search query:
first agg by area, with the path as this is nested. Then reverse to the root document and nested agg to country.
{
"size": 0,
"aggs": {
"agg_areas": {
"nested": {
"path": "areas"
},
"aggs": {
"areas_name": {
"terms": {
"field": "areas.name"
},
"aggs": {
"agg_reverse": {
"reverse_nested": {},
"aggs": {
"agg_countries": {
"nested": {
"path": "countries"
},
"aggs": {
"countries_name": {
"terms": {
"field": "countries.name"
}
}
}
}
}
}
}
}
}
}
}
}
2) retrieve documents:
add a tophits inside your aggregation:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html
top_hits is slow so you will have to read documentation and adjust size and sort to your context.
...
"terms": {
"field": "areas.name"
},
"aggregations": {
"hits": {
"top_hits": { "size": 100}
}
},
...
Using Elasticsearch 2, is it possible to return an aggregation where a document category matches a specific field value? For example, I want to get all the categories where categories.type = "application".
My mapping looks like this:
"mappings": {
"products": {
"_all": {
"enabled": true
},
"properties": {
"title": {
"type": "string"
},
"categories": {
"type":"nested",
"properties": {
"type": {
"type": "string",
"index": "not_analyzed"
},
"name": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
My query looks like this, which returns all category types, but I want to filter just the ones where categories.type = "application".
{
"query":{
"multi_match": {
"query": "Sound",
"fields": [
"title"
]
}
},
"aggs":{
"Applications": {
"nested": {
"path": "categories"
},
"aggs": {
"meta": {
"terms": {
"field": "categories.type"
},
"aggs": {
"name": {
"terms": {
"field": "categories.name"
}
}
}
}
}
}
}
}
You can use aggregation filter if I understand correctly:
{
size : 50,
"query":{
"multi_match": {
"query": "Sound",
"fields": [
"title"
]
}
},
"aggs":{
"Applications": {
"nested": {
"path": "categories"
},
"aggs": {
"meta": {
"filter" : {
"term" : {
"categories.type" : "application"
}
},
"aggs": {
"name": {
"terms": {
"field": "categories.name"
}
}
}
}
}
}
}
}
Hope that helpes.
You just need to replace "include": ".*" to "include": "application"
{
"query":{
"multi_match": {
"query": "Sound",
"fields": [
"title"
]
}
},
"aggs":{
"Applications": {
"nested": {
"path": "categories"
},
"aggs": {
"meta": {
"terms": {
"field": "categories.type"
, "include": "application"
},
"aggs": {
"name": {
"terms": {
"field": "categories.name"
}
}
}
}
}
}
}
}
I'm trying to get the Multi-Field Terms Facet to work, but the results can't seem to do what the documentation (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-facet.html#_multi_fields_2) is saying.
A bit about the setup and the queries I've tried:
I'm using ES 1.1.0:
"name": "William Baker",
"version": {
"number": "1.1.0",
...
}
The mapping:
{
"index_name": {
"mappings": {
"object": {
"properties": {
"nested_object": {
"type": "nested",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string",
"index": "not_analyzed"
}
}
}
...
}
}
}
}
}
The query JSON:
{
"query": {
"filtered": {
"query": {
"match_all": {}
}
}
},
"facets": {
"test4": {
"terms": {
"fields": ["nested_object.name", "nested_object.id"]
},
"nested": "nested_object"
}
}
}
The result:
"facets": {
"test4": {
"_type": "terms",
"missing": 0,
"total": 26,
"other": 12,
"terms": [
{
"term": "Port Anastasia College",
"count": 3
},
{
"term": "31",
"count": 3
},
{
"term": "Zorahaven College",
"count": 1
},
{
"term": "West Lonzoview College",
"count": 1
},
...
]
}
}
I don't understand why the query is returning only the first ID, and as a separate term, instead of an aggregation of the two, as described in the documentation.
I'd appreciate any idea on how to get this multi-field facet to work.
Thanks.