直方图(histogram)聚合edit

一个基于值源(value source)的多桶聚合,可应用于从文档中提取的数值或数值范围值。 它根据值动态构建固定大小(也称为间隔/interval)的桶。 例如,如果文档有一个保存价格price(数字)的字段,我们可以配置这个聚合来动态构建间隔为5的桶(本例中是价格,则它可以表示5元)。 执行聚合时,将计算每个文档的 price 字段,并将其向下舍入到最接近的桶——例如,如果价格是32,桶大小是5,则舍入将得到30,因此该文档将“落入”与键30相关联的桶。 为了更正式,这里使用了舍入函数:

bucket_key = Math.floor((value - offset) / interval) * interval + offset

对于范围值,一个文档可能会落入多个桶。 第一个桶从范围的下限开始计算,计算方式与计算单个值的桶相同。 最后一个桶以相同的方式从范围的上限开始计算,范围计入这两个桶之间(含)的所有桶。

interval必须是正的小数,而offset必须是[0, interval)中的数(大于或等于0且小于interval的小数)

下面的代码片段根据price50为间隔对产品进行“分桶”:

POST /sales/_search?size=0
{
    "aggs" : {
        "prices" : {
            "histogram" : {
                "field" : "price",
                "interval" : 50
            }
        }
    }
}

响应可能如下所示:

{
    ...
    "aggregations": {
        "prices" : {
            "buckets": [
                {
                    "key": 0.0,
                    "doc_count": 1
                },
                {
                    "key": 50.0,
                    "doc_count": 1
                },
                {
                    "key": 100.0,
                    "doc_count": 0
                },
                {
                    "key": 150.0,
                    "doc_count": 2
                },
                {
                    "key": 200.0,
                    "doc_count": 3
                }
            ]
        }
    }
}

最小文档数量

上面的响应显示没有文档的 price 在[100, 150)范围内。 默认情况下,响应将用空桶填充直方图中的间隙。 得益于min_doc_count设置,可以更改和请求具有更高最小数量的桶:

POST /sales/_search?size=0
{
    "aggs" : {
        "prices" : {
            "histogram" : {
                "field" : "price",
                "interval" : 50,
                "min_doc_count" : 1
            }
        }
    }
}

响应:

{
    ...
    "aggregations": {
        "prices" : {
            "buckets": [
                {
                    "key": 0.0,
                    "doc_count": 1
                },
                {
                    "key": 50.0,
                    "doc_count": 1
                },
                {
                    "key": 150.0,
                    "doc_count": 2
                },
                {
                    "key": 200.0,
                    "doc_count": 3
                }
            ]
        }
    }
}

默认情况下,histogram返回数据本身范围内的所有桶,也就是说,具有最小值的文档(使用直方图)将确定最小桶(具有最小键的桶),具有最大值的文档将确定最大桶(具有最大键的桶)。 通常,当请求空桶时,这会导致混乱,特别是当数据也被过滤时。

为了理解其中的原因,我们来看一个例子:

假设你正在过滤你的请求,以获取值在0500之间的所有文档,此外,你希望使用间隔为50的直方图来分割每个价格的数据。 你还指定了"min_doc_count" : 0,因为你希望获得所有的桶,即使是空的桶。 如果碰巧所有产品(文档)的价格都高于 100,那么你将得到的第一个桶将是以100为键的桶。 这是令人困惑的,因为很多时候,你也想得到0 - 100之间的那些桶。

通过extended_bounds设置,你现在可以“强制” histogram 聚合开始根据特定的min值构建桶,并继续构建桶直到max值(即使不再有文档)。 仅当min_doc_count为 0 时,使用extended_bounds才有意义(如果min_doc_count大于0,则永远不会返回空桶)。

注意(顾名思义), extended_bounds是过滤桶。 也就是说,如果extended_bounds.min高于从文档中提取的值,文档仍将指示第一个桶将是什么(extended_bounds.max和最后一个桶也是如此)。 对于过滤桶,应该使用适当的from/to设置将 histogram 聚合嵌套在范围filter聚合下。

示例:

POST /sales/_search?size=0
{
    "query" : {
        "constant_score" : { "filter": { "range" : { "price" : { "to" : "500" } } } }
    },
    "aggs" : {
        "prices" : {
            "histogram" : {
                "field" : "price",
                "interval" : 50,
                "extended_bounds" : {
                    "min" : 0,
                    "max" : 500
                }
            }
        }
    }
}

聚合范围时,桶基于返回的文档的值。 这意味着响应可能包含查询范围之外的桶。 例如,如果查询是要查找大于100的值,并且范围从50到150,interval为50,那么该文档将位于3个桶中——50、100和150。 一般来说,最好将查询和聚合步骤看作是独立的——查询负责选择一组文档,然后聚合对这些文档进行分桶,而不考虑它们是如何被选择的。 更多信息和示例参考 有关范围字段分桶的提示

order

默认情况下,返回的桶按它们的key升序排序,尽管可以使用order设置来控制排序行为。 支持与terms 聚合相同的order功能。

Offset

默认情况下,桶的键从0开始,然后以interval的均匀步长继续,例如,如果 interval 是10,前三个桶(假设其中有数据)将是[0, 10)[10, 20)[20, 30)。 可以通过使用offset选项来移动桶的边界。

这可以用一个例子来说明。 如果有10个值在5到14之间的文档,使用间隔10将产生两个桶,每个桶有5个文档。 如果使用额外的5 5,将只有一个包含所有10个文档的桶[5, 15)

响应格式

默认情况下,桶作为有序数组返回。 也可以请求以哈希形式的响应,而不是以桶的键作为键:

POST /sales/_search?size=0
{
    "aggs" : {
        "prices" : {
            "histogram" : {
                "field" : "price",
                "interval" : 50,
                "keyed" : true
            }
        }
    }
}

响应:

{
    ...
    "aggregations": {
        "prices": {
            "buckets": {
                "0.0": {
                    "key": 0.0,
                    "doc_count": 1
                },
                "50.0": {
                    "key": 50.0,
                    "doc_count": 1
                },
                "100.0": {
                    "key": 100.0,
                    "doc_count": 0
                },
                "150.0": {
                    "key": 150.0,
                    "doc_count": 2
                },
                "200.0": {
                    "key": 200.0,
                    "doc_count": 3
                }
            }
        }
    }
}

缺失的值

参数missing定义应该如何处理有缺失值的文档。 默认情况下,它们将被忽略,但也可以将它们视为有一个值。

POST /sales/_search?size=0
{
    "aggs" : {
        "quantity" : {
             "histogram" : {
                 "field" : "quantity",
                 "interval": 10,
                 "missing": 0 
             }
         }
    }
}

字段quantity中没有值的文档将与值为0的文档落入同一个桶中。