Как добавить пейджинг в агрегацию Elasticsearch?

У меня есть запрос эластичного поиска, как показано ниже:

{
    "size":0,
    "aggs":{
        "group_by_state":{
            "terms":{
                "field":"poi_id"
            },
            "aggs":{
                "sum(price)":{
                    "sum":{
                        "field":"price"
                    }
                }
            }
        }
    }
}

Я хочу добавить подкачку в этом запросе, так же, как

select poi_id, sum(price) from table group by poi_id limit 0,2

Я много искал и нашел ссылку об этом: https://github.com/elastic/elasticsearch/issues/4915.

Но все же я не получил метод реализации.

Есть ли способ реализовать это самим Elasticsearch, но не моим приложением?

2 ответа

В настоящее время я работаю над решением для агрегации результатов подкачки. То, что вы хотите использовать, это partition, Этот раздел в официальных документах очень полезен. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html

Чтобы адаптировать ваш пример, terms Настройка будет обновлена ​​следующим образом.

{
    "size":0,
    "aggs":{
        "group_by_state":{
            "terms":{
                "field":"poi_id",
                "include": {
                    "partition": 0,
                    "num_of_partitions": 100
                },
                "size": 10000
            },
            "aggs":{
                "sum(price)":{
                    "sum":{
                        "field":"price"
                    }
                }
            }
        }
    }
}

Это сгруппирует ваши результаты в 100 разделов (num_of_partitions) с максимальным размером 10 Кбайт в каждом (size) и получить первый такой раздел (partition: 0)

Если у вас есть более 10 000 уникальных значений для поля, по которому вы агрегируете (и хотите вернуть все значения), вы захотите увеличить size значение или потенциально вычислить size а также num_of_partitions динамически в зависимости от мощности вашего поля. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html

Вы также можете использовать show_term_doc_count_error настройка, чтобы убедиться, что ваша агрегация возвращает точные значения. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html

Надеюсь, это полезно.

Поздно к вечеринке, но только что обнаружил "составные" агрегаты в v6.3+. Это позволяет:
1. Группировка, более похожая на Sql.
2. Разбиение на страницы с помощью ключа after_key.
Спасли наши дни, надеюсь, это поможет и другим.

Пример получения количества обращений в час между двумя датами, сгруппированными по 5 полям:

GET myindex-idx/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"docType": "myDOcType"}}, 
        {"range": {
          "@date": {"gte": "2019-06-19T21:00:00", "lt": "2019-06-19T22:00:00"}
          }
        }
      ]
    }
  }, 
  "size": 0, 
  "aggs": {
    "mybuckets": {
      "composite": {
        "size": 100, 
        "sources": [
          {"@date": {
            "date_histogram": {
              "field": "@date", 
              "interval": "hour", 
              "format": "date_hour"}
            }
          }, 
          {"field_1": {"terms": {"field": "field_1"}}}, 
          {"field_2": {"terms": {"field": "field_2"}}}, 
          {"field_3": {"terms": {"field": "field_3"}}}, 
          {"field_4": {"terms": {"field": "field_4"}}}, 
          {"field_5": {"terms": {"field": "field_5"}}}
        ]
      }
    }
  }
}

Производит:

{
  "took": 255,
  "timed_out": false,
  "_shards": {
    "total": 80,
    "successful": 80,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 46989,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "mybuckets": {
      "after_key": {
        "@date": "2019-06-19T21",
        "field_1": 262,
        "field_2": 347,
        "field_3": 945,
        "field_4": 2258,
        "field_5": 0
      },
      "buckets": [
        {
          "key": {
            "@date": "2019-06-19T21",
            "field_1": 56,
            "field_2": 106,
            "field_3": 13224,
            "field_4": 46239,
            "field_5": 0
          },
          "doc_count": 3
        },
        {
          "key": {
            "@date": "2019-06-19T21",
            "field_1": 56,
            "field_2": 106,
            "field_3": 32338,
            "field_4": 76919,
            "field_5": 0
          },
          "doc_count": 2
        },
        ....

Следующий запрос разбиения на страницы, выданный таким образом, с использованием объекта after_key в запросах после объекта:

GET myindex-idx/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"docType": "myDOcType"}}, 
        {"range": {
          "@date": {"gte": "2019-06-19T21:00:00", "lt": "2019-06-19T22:00:00"}
          }
        }
      ]
    }
  }, 
  "size": 0, 
  "aggs": {
    "mybuckets": {
      "composite": {
        "size": 100, 
        "sources": [
          {"@date": {
            "date_histogram": {
              "field": "@date", 
              "interval": "hour", 
              "format": "date_hour"}
            }
          }, 
          {"field_1": {"terms": {"field": "field_1"}}}, 
          {"field_2": {"terms": {"field": "field_2"}}}, 
          {"field_3": {"terms": {"field": "field_3"}}}, 
          {"field_4": {"terms": {"field": "field_4"}}}, 
          {"field_5": {"terms": {"field": "field_5"}}}
        ],
      "after": {
        "@date": "2019-06-19T21",
        "field_1": 262,
        "field_2": 347,
        "field_3": 945,
        "field_4": 2258,
        "field_5": 0
        }
      }
    }
  }
}

Это пролистывает результаты, пока mybuckets не вернет пустой

Вы можете использовать параметры и размер в вашем запросе. См. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-from-size.html для получения дополнительной информации. Ваш запрос будет примерно таким:

{
    "from" : 0, 
    "size" : 10,
    "aggs":{
        "group_by_state":{
            "terms":{
                "field":"poi_id"
            },
            "aggs":{
                "sum(price)":{
                    "sum":{
                        "field":"price"
                    }
                }
            }
        }
    }
}
Другие вопросы по тегам