Как получить агрегацию Elasticsearch с несколькими полями
Я пытаюсь найти связанные теги с тем, который в настоящее время просматривается. Каждый документ в нашем индексе помечен. Каждый тег состоит из двух частей-ID и текстового имени:
{
...
meta: {
...
tags: [
{
id: 123,
name: 'Biscuits'
},
{
id: 456,
name: 'Cakes'
},
{
id: 789,
name: 'Breads'
}
]
}
}
чтобы получить связанные теги, я просто запрашиваю документы и получаю совокупность их тегов:
{
"query": {
"bool": {
"must": [
{
"match": {
"item.meta.tags.id": "123"
}
},
{
...
}
]
}
},
"aggs": {
"baked_goods": {
"terms": {
"field": "item.meta.tags.id",
"min_doc_count": 2
}
}
}
}
это работает отлично, я получаю результаты, которые я хочу. Тем не менее, мне нужны оба тега ID и имя, чтобы сделать что-нибудь полезное. Я исследовал, как этого решения представляется:
- объединить поля при индексации
- сценарий, чтобы munge вместе поля
- вложенные агрегации
вариант один и два недоступны для меня, поэтому я собирался с 3, но он не отвечает ожидаемым образом. Учитывая следующий запрос (все еще поиск документов, также помеченных "печенье"):
{
...
"aggs": {
"baked_goods": {
"terms": {
"field": "item.meta.tags.id",
"min_doc_count": 2
},
"aggs": {
"name": {
"terms": {
"field": "item.meta.tags.name"
}
}
}
}
}
}
Я вам это результат:
{
...
"aggregations": {
"baked_goods": {
"buckets": [
{
"key": "456",
"doc_count": 11,
"name": {
"buckets": [
{
"key": "Biscuits",
"doc_count": 11
},
{
"key": "Cakes",
"doc_count": 11
}
]
}
}
]
}
}
}
вложенная агрегация включает в себя как поисковый термин и тег, который я ищу (возвращается в алфавитном порядке).
Я попытался смягчить это, добавив exclude
к вложенной агрегации, но это слишком сильно замедлило запрос (около 100 раз для 500000 документов). До сих пор самым быстрым решением является де-dupe результат вручную.
каков наилучший способ получить агрегацию тегов с идентификатором тега и тегом имя в ответе?
Спасибо за это!
1 ответов
судя по всему, ваш tags
- это не nested
.
Чтобы эта агрегация работала,вам понадобится nested
так что существует связь между id
и a name
. Без nested
список id
s - это просто массив и список name
s-Еще один массив:
"item": {
"properties": {
"meta": {
"properties": {
"tags": {
"type": "nested", <-- nested field
"include_in_parent": true, <-- to, also, keep the flat array-like structure
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
кроме того, обратите внимание, что я добавил к сопоставлению эту строку "include_in_parent": true
что означает nested
теги также будут вести себя как" плоский " массив-как структура.
Итак, все, что у вас было до сих пор в ваших запросах, будет работать без каких-либо изменений в запросах.
но для этого конкретного вашего запроса агрегация должна измениться на что-то вроде этого:
{
"aggs": {
"baked_goods": {
"nested": {
"path": "item.meta.tags"
},
"aggs": {
"name": {
"terms": {
"field": "item.meta.tags.id"
},
"aggs": {
"name": {
"terms": {
"field": "item.meta.tags.name"
}
}
}
}
}
}
}
}
и результат такой:
"aggregations": {
"baked_goods": {
"doc_count": 9,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 123,
"doc_count": 3,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "biscuits",
"doc_count": 3
}
]
}
},
{
"key": 456,
"doc_count": 2,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "cakes",
"doc_count": 2
}
]
}
},
.....