Как получить последние значения для каждой группы с запросом Elasticsearch?
У меня есть документы, индексированные на Elasticsearch, похожие на эти образцы:
{'country': 'France', 'collected': '2015-03-12', 'value': 20}
{'country': 'Canada', 'collected': '2015-03-12', 'value': 21}
{'country': 'Brazil', 'collected': '2015-03-12', 'value': 33}
{'country': 'France', 'collected': '2015-02-01', 'value': 10}
{'country': 'Canada', 'collected': '2015-02-01', 'value': 11}
{'country': 'Mexico', 'collected': '2015-02-01', 'value': 9}
...
Я хочу построить запрос, который получает один результат для каждой страны, получая только те, у которых max(collected)
.
Итак, для примеров, показанных выше, результаты будут выглядеть примерно так:
{'country': 'France', 'collected': '2015-03-12', 'value': 20}
{'country': 'Canada', 'collected': '2015-03-12', 'value': 21}
{'country': 'Brazil', 'collected': '2015-03-12', 'value': 33}
{'country': 'Mexico', 'collected': '2015-02-01', 'value': 9}
Я понял, что мне нужно сделать агрегацию на country
, но я не понимаю, как ограничить результаты на max(collected)
.
Любые идеи?
Ответы
Ответ 1
Вы можете использовать агрегацию top_hits
, которая группируется в поле country
, возвращает 1 документ на группу и заказывает документы по набранной дате по убыванию:
POST /test/_search?search_type=count
{
"aggs": {
"group": {
"terms": {
"field": "country"
},
"aggs": {
"group_docs": {
"top_hits": {
"size": 1,
"sort": [
{
"collected": {
"order": "desc"
}
}
]
}
}
}
}
}
}
Ответ 2
Для таких, как user1892775, которые запускаются в "Fielddata отключено по текстовым полям по умолчанию...", вы можете создать многопользовательское поле (https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html). Таким образом, вы можете иметь сопоставление, например:
"mapping": {
"properties": {
"country": {"type": "string", "fields": {"raw": {"type": "string", "index": "not_analyzed"}}}
}
Тогда ваш запрос будет выглядеть как
POST /test/_search?search_type=count
{
"aggs": {
"group": {
"terms": {
"field": "country.raw"
},
"aggs": {
"group_docs": {
"top_hits": {
"size": 1,
"sort": [
{
"collected": {
"order": "desc"
}
}
]
}
}
}
}
}
}
(Обратите внимание на использование страны. raw)