Подтвердить что ты не робот

Как получить последние значения для каждой группы с запросом 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).

Любые идеи?

4b9b3361

Ответ 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)