Добавление дополнительных полей в агрегацию терминов ElasticSearch
Индексированные документы выглядят следующим образом:
{
id: 1,
title: 'Blah',
...
platform: {id: 84, url: 'http://facebook.com', title: 'Facebook'}
...
}
То, что я хочу, это подсчет и вывод статистики по платформе.
Для подсчета я могу использовать агрегирование терминов с platform.id
как поле для подсчета:
aggs: {
platforms: {
terms: {field: 'platform.id'}
}
}
Таким образом, я получаю статистику как несколько ведер, выглядящих как {key: 8, doc_count: 162511}
, как и ожидалось.
Теперь, могу ли я как-то добавить к этим ковшим также platform.name
и platform.url
(для отличного вывода статистики)? Самое лучшее, что я придумал, выглядит так:
aggs: {
platforms: {
terms: {field: 'platform.id'},
aggs: {
name: {terms: {field: 'platform.name'}},
url: {terms: {field: 'platform.url'}}
}
}
}
На самом деле, работает и возвращает довольно сложную структуру в каждом ковше:
{key: 7,
doc_count: 528568,
url:
{doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{key: "http://facebook.com", doc_count: 528568}]},
name:
{doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{key: "Facebook", doc_count: 528568}]}},
Конечно, имя и URL-адрес платформы можно извлечь из этой структуры (например, bucket.url.buckets.first.key
), но есть ли более простой и простой способ выполнить задачу?
Ответы
Ответ 1
Кажется, лучший способ показать намерения - это top hits aggregation: "из каждой агрегированной группы выберите только один документ", а затем извлеките из нее платформу:
aggs: {
platforms: {
terms: {field: 'platform.id'},
aggs: {
platform: {top_hits: {size: 1, _source: {include: ['platform']}}}
}
}
Таким образом, каждый из них будет выглядеть следующим образом:
{"key": 7,
"doc_count": 529939,
"platform": {
"hits": {
"hits": [{
"_source": {
"platform":
{"id": 7, "name": "Facebook", "url": "http://facebook.com"}
}
}]
}
},
}
Какая-то слишком изощренная (как обычно, с ES), но чистая: bucket.platform.hits.hits.first._source.platform
Ответ 2
Если вам не обязательно нужно получить значение platform.id
, вы можете уйти с одной агрегацией, используя script
, который объединяет два поля name
и url
:
aggs: {
platforms: {
terms: {script: 'doc["platform.name"].value + "," + doc["platform.url"].value'}
}
}