范围字段分组的细微差别
编辑范围字段分组的细微差别编辑
文档会被计入它们所属的每个分组编辑
由于范围代表多个值,因此对范围字段运行分组聚合会导致同一文档落在多个分组中。这会导致令人惊讶的行为,例如分组计数的总和高于匹配文档的数量。例如,考虑以下索引
response = client.indices.create( index: 'range_index', body: { settings: { number_of_shards: 2 }, mappings: { properties: { expected_attendees: { type: 'integer_range' }, time_frame: { type: 'date_range', format: 'yyyy-MM-dd||epoch_millis' } } } } ) puts response response = client.index( index: 'range_index', id: 1, refresh: true, body: { expected_attendees: { gte: 10, lte: 20 }, time_frame: { gte: '2019-10-28', lte: '2019-11-04' } } ) puts response
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" } }
以下聚合中的范围比间隔更宽,因此文档将落在多个分组中。
response = client.search( index: 'range_index', size: 0, body: { aggregations: { range_histo: { histogram: { field: 'expected_attendees', interval: 5 } } } } ) puts response
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 } ] } } }
文档不能部分存在于分组中;例如,上面的文档不能在上述三个分组中的每一个中计为三分之一。在本例中,由于文档的范围落在多个分组中,因此该文档的完整值也将计入每个分组的任何子聚合中。
查询边界不是聚合过滤器编辑
当使用查询过滤要聚合的字段时,可能会出现另一种意外行为。在这种情况下,文档可能与查询匹配,但其范围的端点之一或两个端点都可能在查询之外。考虑对上述文档进行以下聚合
response = client.search( index: 'range_index', size: 0, body: { query: { range: { time_frame: { gte: '2019-11-01', format: 'yyyy-MM-dd' } } }, aggregations: { november_data: { date_histogram: { field: 'time_frame', calendar_interval: 'day', format: 'yyyy-MM-dd' } } } } ) puts response
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" } } } }
即使查询只考虑 11 月份的天数,聚合也会生成 8 个分组(10 月份 4 个,11 月份 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
查询可以将文档限制为仅那些完全落在查询范围内的文档。在本例中,该文档将不会被包含,并且聚合将为空。在用例中,如果需要对文档进行计数,但可以安全地忽略超出范围的数据,也可以在聚合之后过滤分组。