Агрегации
Агрегация подытоживает данные в виде метрик, статистических данных или других аналитических показателей. Агрегации помогают ответить на вопросы, такие как:
- Каково среднее время загрузки моего веб-сайта?
- Кто мои самые ценные клиенты на основе объема транзакций?
- Какой файл считается большим в моей сети?
- Сколько продуктов в каждой категории продуктов?
Elasticsearch организует агрегации в три категории:
- Метрические агрегации, которые вычисляют метрики, такие как сумма или среднее значение, из значений полей.
- Агрегации по корзинам, которые группируют документы в корзины (также называемые ячейками) на основе значений полей, диапазонов или других критериев.
- Агрегации конвейера, которые берут входные данные из других агрегаций вместо документов или полей.
Выполнение агрегации
Вы можете выполнить агрегации в рамках запроса поиска, указав параметр API поиска's aggs. Следующий запрос выполняет агрегацию по типам для my-field:
resp = client.search(
index="my-index-000001",
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
},
},
});
console.log(response); GET /my-index-000001/_search
{
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
}
} Результаты агрегации находятся в объекте aggregations ответа:
{
"took": 78,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.0,
"hits": [...]
},
"aggregations": {
"my-agg-name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": []
}
}
} | Результаты для |
Изменение области действия агрегации
Используйте параметр query, чтобы ограничить документы, на которых выполняется агрегация:
resp = client.search(
index="my-index-000001",
query={
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
},
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
query: {
range: {
"@timestamp": {
gte: 'now-1d/d',
lt: 'now/d'
}
}
},
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
query: {
range: {
"@timestamp": {
gte: "now-1d/d",
lt: "now/d",
},
},
},
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
},
},
});
console.log(response); GET /my-index-000001/_search
{
"query": {
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
},
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
}
} Возврат только результатов агрегации
По умолчанию запросы, содержащие агрегацию, возвращают как результаты поиска, так и результаты агрегации. Для возврата только результатов агрегации установите size в значение 0:
resp = client.search(
index="my-index-000001",
size=0,
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
size: 0,
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
size: 0,
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
},
},
});
console.log(response); GET /my-index-000001/_search
{
"size": 0,
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
}
} Выполнение нескольких агрегаций
Вы можете указать несколько агрегаций в одном запросе:
resp = client.search(
index="my-index-000001",
aggs={
"my-first-agg-name": {
"terms": {
"field": "my-field"
}
},
"my-second-agg-name": {
"avg": {
"field": "my-other-field"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-first-agg-name": {
terms: {
field: 'my-field'
}
},
"my-second-agg-name": {
avg: {
field: 'my-other-field'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
aggs: {
"my-first-agg-name": {
terms: {
field: "my-field",
},
},
"my-second-agg-name": {
avg: {
field: "my-other-field",
},
},
},
});
console.log(response); GET /my-index-000001/_search
{
"aggs": {
"my-first-agg-name": {
"terms": {
"field": "my-field"
}
},
"my-second-agg-name": {
"avg": {
"field": "my-other-field"
}
}
}
} Выполнение под-агрегаций
Агрегации по корзинам поддерживают под-агрегации по корзинам или метрикам. Например, агрегация по типам с под-агрегацией avg вычисляет среднее значение для каждой корзины документов. Вложенность под-агрегаций не имеет ограничений по уровням или глубине.
resp = client.search(
index="my-index-000001",
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
},
"aggs": {
"my-sub-agg-name": {
"avg": {
"field": "my-other-field"
}
}
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
},
aggregations: {
"my-sub-agg-name": {
avg: {
field: 'my-other-field'
}
}
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
aggs: {
"my-sub-agg-name": {
avg: {
field: "my-other-field",
},
},
},
},
},
});
console.log(response); GET /my-index-000001/_search
{
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
},
"aggs": {
"my-sub-agg-name": {
"avg": {
"field": "my-other-field"
}
}
}
}
}
} Ответ вкладывает результаты под-агрегаций под родительскую агрегацию:
{
...
"aggregations": {
"my-agg-name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "foo",
"doc_count": 5,
"my-sub-agg-name": {
"value": 75.0
}
}
]
}
}
} | Результаты родительской агрегации, | |
| Результаты под-агрегации |
Добавление пользовательских метаданных
Используйте объект meta, чтобы связать пользовательские метаданные с агрегацией:
resp = client.search(
index="my-index-000001",
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
},
"meta": {
"my-metadata-field": "foo"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
},
meta: {
"my-metadata-field": 'foo'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
meta: {
"my-metadata-field": "foo",
},
},
},
});
console.log(response); GET /my-index-000001/_search
{
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
},
"meta": {
"my-metadata-field": "foo"
}
}
}
} Ответ возвращает объект meta на его месте:
{
...
"aggregations": {
"my-agg-name": {
"meta": {
"my-metadata-field": "foo"
},
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": []
}
}
} Возврат типа агрегации
По умолчанию результаты агрегации включают имя агрегации, но не ее тип. Для возврата типа агрегации используйте параметр запроса typed_keys.
resp = client.search(
index="my-index-000001",
typed_keys=True,
aggs={
"my-agg-name": {
"histogram": {
"field": "my-field",
"interval": 1000
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
typed_keys: true,
body: {
aggregations: {
"my-agg-name": {
histogram: {
field: 'my-field',
interval: 1000
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
typed_keys: "true",
aggs: {
"my-agg-name": {
histogram: {
field: "my-field",
interval: 1000,
},
},
},
});
console.log(response); GET /my-index-000001/_search?typed_keys
{
"aggs": {
"my-agg-name": {
"histogram": {
"field": "my-field",
"interval": 1000
}
}
}
} Ответ возвращает тип агрегации как префикс к имени агрегации.
Некоторые агрегации возвращают другой тип агрегации, чем тип в запросе. Например, агрегации по типам, значимых терминов и перцентилей возвращают разные типы агрегаций в зависимости от типа данных агрегируемого поля.
{
...
"aggregations": {
"histogram#my-agg-name": {
"buckets": []
}
}
} | Тип агрегации, |
Использование скриптов в агрегации
Когда поле неточно соответствует нужной агрегации, вы должны агрегировать по полю runtime:
resp = client.search(
index="my-index-000001",
size="0",
runtime_mappings={
"message.length": {
"type": "long",
"script": "emit(doc['message.keyword'].value.length())"
}
},
aggs={
"message_length": {
"histogram": {
"interval": 10,
"field": "message.length"
}
}
},
)
print(resp) const response = await client.search({
index: "my-index-000001",
size: 0,
runtime_mappings: {
"message.length": {
type: "long",
script: "emit(doc['message.keyword'].value.length())",
},
},
aggs: {
message_length: {
histogram: {
interval: 10,
field: "message.length",
},
},
},
});
console.log(response); GET /my-index-000001/_search?size=0
{
"runtime_mappings": {
"message.length": {
"type": "long",
"script": "emit(doc['message.keyword'].value.length())"
}
},
"aggs": {
"message_length": {
"histogram": {
"interval": 10,
"field": "message.length"
}
}
}
} Скрипты вычисляют значения полей динамически, что добавляет небольшую нагрузку на агрегацию. Помимо времени вычисления, некоторые агрегации, такие как terms и filters, не могут использовать некоторые свои оптимизации с полями runtime. В целом, затраты на производительность при использовании поля runtime варьируются от агрегации к агрегации.
Кэши агрегаций
Для более быстрых ответов Elasticsearch кэширует результаты часто выполняемых агрегаций в кэше запросов фрагментов. Чтобы получить кэшированные результаты, используйте одну и ту же строку preference для каждого запроса. Если вам не нужны результаты поиска, установите size в значение 0, чтобы избежать заполнения кэша.
Elasticsearch направляет запросы с одной и той же строкой предпочтений на одни и те же фрагменты. Если данные фрагментов не меняются между запросами, фрагменты возвращают кэшированные результаты агрегаций.
Пределы для значений long
При выполнении агрегаций Elasticsearch использует значения double для хранения и представления числовых данных. В результате агрегации по long числам, превышающим 253, являются приближенными.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/search-aggregations.html