Особенности агрегирования по диапазонам полей
Документы учитываются для каждой попадающей в неё категории
Поскольку диапазон представляет собой множество значений, применение агрегирования по категориям к полю диапазона может привести к тому, что один и тот же документ попадет в несколько категорий. Это может привести к неожиданному поведению, например, к тому, что сумма подсчётов категорий будет больше, чем количество сопоставленных документов. Рассмотрим следующий индекс:
PUT range_index
{
"settings": {
"number_of_shards": 2
},
"mappings": {
"properties": {
"expected_attendees": {
"type": "integer_range"
},
"time_frame": {
"type": "date_range",
"format": "yyyy-MM-dd||epoch_millis"
}
}
}
}
PUT range_index/_doc/1?refresh
{
"expected_attendees" : {
"gte" : 10,
"lte" : 20
},
"time_frame" : {
"gte" : "2019-10-28",
"lte" : "2019-11-04"
}
} Диапазон шире интервала в следующей агрегации, поэтому документ попадет в несколько категорий.
POST /range_index/_search?size=0
{
"aggs": {
"range_histo": {
"histogram": {
"field": "expected_attendees",
"interval": 5
}
}
}
} Поскольку интервал равен 5 (а смещение по умолчанию равно 0), мы ожидаем категории 10, 15 и 20. Наш документ попадает во все три категории.
{
...
"aggregations" : {
"range_histo" : {
"buckets" : [
{
"key" : 10.0,
"doc_count" : 1
},
{
"key" : 15.0,
"doc_count" : 1
},
{
"key" : 20.0,
"doc_count" : 1
}
]
}
}
} Документ не может частично находиться в категории; например, вышеупомянутый документ не может считаться одной третью в каждой из трёх упомянутых категорий. В этом примере, так как диапазон документа попал в несколько категорий, полное значение этого документа также будет учтено во всех под-агрегациях для каждой категории.
Границы запроса не являются фильтрами агрегации
Другое неожиданное поведение может возникнуть при использовании запроса для фильтрации по агрегируемому полю. В этом случае документ может соответствовать запросу, но при этом один или оба конца диапазона могут находиться вне запроса. Рассмотрим следующую агрегацию для вышеупомянутого документа:
POST /range_index/_search?size=0
{
"query": {
"range": {
"time_frame": {
"gte": "2019-11-01",
"format": "yyyy-MM-dd"
}
}
},
"aggs": {
"november_data": {
"date_histogram": {
"field": "time_frame",
"calendar_interval": "day",
"format": "yyyy-MM-dd"
}
}
}
} Несмотря на то, что запрос учитывает только дни ноября, агрегация генерирует 8 категорий (4 в октябре, 4 в ноябре), потому что агрегация рассчитывается по диапазонам всех соответствующих документов.
{
...
"aggregations" : {
"november_data" : {
"buckets" : [
{
"key_as_string" : "2019-10-28",
"key" : 1572220800000,
"doc_count" : 1
},
{
"key_as_string" : "2019-10-29",
"key" : 1572307200000,
"doc_count" : 1
},
{
"key_as_string" : "2019-10-30",
"key" : 1572393600000,
"doc_count" : 1
},
{
"key_as_string" : "2019-10-31",
"key" : 1572480000000,
"doc_count" : 1
},
{
"key_as_string" : "2019-11-01",
"key" : 1572566400000,
"doc_count" : 1
},
{
"key_as_string" : "2019-11-02",
"key" : 1572652800000,
"doc_count" : 1
},
{
"key_as_string" : "2019-11-03",
"key" : 1572739200000,
"doc_count" : 1
},
{
"key_as_string" : "2019-11-04",
"key" : 1572825600000,
"doc_count" : 1
}
]
}
}
} В зависимости от сценария использования, запрос CONTAINS может ограничить документы только теми, которые полностью попадают в запрошенный диапазон. В этом примере один документ не будет включен, и агрегация будет пустой. Фильтрация категорий после агрегации также является вариантом для случаев, когда документ должен быть учтён, но данные, выходящие за пределы диапазона, могут быть безопасно проигнорированы.
© 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/7.17/search-aggregations-bucket-range-field-note.html