Как добавить пейджинг в агрегацию 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"
}
}
}
}
}
}