Histogram Aggregation

原文链接 : https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-histogram-aggregation.html

译文链接 : http://www.apache.wiki/display/Elasticsearch(修改该链接为 ApacheCN 对应的译文链接)

贡献者 : @于永超,ApacheCNApache中文网

Histogram Aggregation

A multi-bucket values source based aggregation,可以应用于从文档中提取的数值。它会动态地在值上构建固定大小(a.k.a.interval)桶。例如,如果文档有一个包含价格的字段(数值),我们可以配置这个聚合来动态地构建带间隔5的bucket(比如价格可能代表$ 5),当聚合执行时,每个文档的价格字段将被评估,并将四舍五入到最接近的bucket,例如,如果价格是32,而bucket(桶)的大小是5,那么四舍五入将产生30,因此,文档将“掉落”到与关键30相关的bucket(桶)中,为了使这更正式,这里是使用的如下计算公式:

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

interval必须是正数,而offset(偏移量)必须是小数[0, interval[.

下面的代码片段“bucket”基于价格的间隔为50

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50
  8. }
  9. }
  10. }
  11. }

可能返回以下结果:

  1. {
  2. ...
  3. "aggregations": {
  4. "prices" : {
  5. "buckets": [
  6. {
  7. "key": 0.0,
  8. "doc_count": 1
  9. },
  10. {
  11. "key": 50.0,
  12. "doc_count": 1
  13. },
  14. {
  15. "key": 100.0,
  16. "doc_count": 0
  17. },
  18. {
  19. "key": 150.0,
  20. "doc_count": 2
  21. },
  22. {
  23. "key": 200.0,
  24. "doc_count": 3
  25. }
  26. ]
  27. }
  28. }
  29. }

Minimum document count

上面的结果显示,没有任何文档的价格在[100 - 150)范围内。默认情况下,返回结果将用空桶填充直方图中的空白。由于min_doc_count设置,可能会更改这个和请求桶的最小值,这是由min_doc_count设置:

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50,
  8. "min_doc_count" : 1
  9. }
  10. }
  11. }
  12. }

返回结果:

  1. {
  2. ...
  3. "aggregations": {
  4. "prices" : {
  5. "buckets": [
  6. {
  7. "key": 0.0,
  8. "doc_count": 1
  9. },
  10. {
  11. "key": 50.0,
  12. "doc_count": 1
  13. },
  14. {
  15. "key": 150.0,
  16. "doc_count": 2
  17. },
  18. {
  19. "key": 200.0,
  20. "doc_count": 3
  21. }
  22. ]
  23. }
  24. }
  25. }

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

为了说明原因,让我们来看一下列子:

假设你正在过滤您的请求,以获取值在0到500之间的所有文档,此外,您还希望使用直方图来将数据切片,其中间隔为50,您还要指定“min_doc_count”:0,因为您希望获得所有的桶,即使是空的。如果发生这种情况,所有产品(文件)的价格都高于100,你将获得的第一个bucket将是一个100的key,这是令人困惑的,很多次,你还想把这些桶放在0到100之间。

通过使用extended_bounds设置,现在,您可以“强制”直方图聚合来开始在特定的min值上构建bucket,并且还可以继续构建到最大值的bucket(即使没有文档了),当min_doc_count为0时,使用extended_bounds才有意义(如果min_doc_count大于0,则永远不会返回空buckets)

注意,(顾名思义)extended_bounds不是过滤buckets。意味着,如果extended_bounds.min高于从文档中提取的值。这些文件仍将决定第一个bucket将是什么(对于extended_bounds.max和最后一个bucket也是一样),对于filtering buckets,应使用适当的from/to设置将范围过滤器聚合下的直方图聚合嵌套。

例子:

  1. POST /sales/_search?size=0
  2. {
  3. "query" : {
  4. "constant_score" : { "filter": { "range" : { "price" : { "to" : "500" } } } }
  5. },
  6. "aggs" : {
  7. "prices" : {
  8. "histogram" : {
  9. "field" : "price",
  10. "interval" : 50,
  11. "extended_bounds" : {
  12. "min" : 0,
  13. "max" : 500
  14. }
  15. }
  16. }
  17. }
  18. }

Order

默认情况下,返回的bucket按它们的key升序排序,尽管顺序行为可以通过order设置来控制。

按键降序排列桶:

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50,
  8. "order" : { "_key" : "desc" }
  9. }
  10. }
  11. }
  12. }

按其doc_count - 升序排列:

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50,
  8. "order" : { "_count" : "asc" }
  9. }
  10. }
  11. }
  12. }

If the histogram aggregation has a direct metrics sub-aggregation, 则后者可以确定桶的顺序:

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50,
  8. "order" : { "price_stats.min" : "asc" } #1
  9. },
  10. "aggs" : {
  11. "price_stats" : { "stats" : {"field" : "price"} }
  12. }
  13. }
  14. }
  15. }

1 {“price_stats.min”:asc“}将根据其price_stats子聚合的最小值对桶进行排序。也可以根据层次结构中的“更深层次的”聚合来对buckets进行排序,只要聚合路径是single-bucket类型,就可以支持这一点,在路径中的最后一个聚合可能是单桶的,也可以是度量的。如果它是一个single-bucket类型,那么这个顺序将由bucket中的文档数来定义(例如doc_count),如果这是一个度量标准,则与上面的规则相同(如果路径必须指出度量名称以在multi-value度量聚合的情况下排序,并且在single-value度量聚合的情况下,该排序将应用于该值)

路径必须以下列形式定义:

  1. AGG_SEPARATOR = '>' ;
  2. METRIC_SEPARATOR = '.' ;
  3. AGG_NAME = <the name of the aggregation> ;
  4. METRIC = <the name of the metric (in case of multi-value metrics aggregation)> ;
  5. PATH = <AGG_NAME> [ <AGG_SEPARATOR>, <AGG_NAME> ]* [ <METRIC_SEPARATOR>, <METRIC> ] ;
  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50,
  8. "order" : { "promoted_products>rating_stats.avg" : "desc" }
  9. },
  10. "aggs" : {
  11. "promoted_products" : {
  12. "filter" : { "term" : { "promoted" : true }},
  13. "aggs" : {
  14. "rating_stats" : { "stats" : { "field" : "rating" }}
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }

上述将根据促销产品的平均评级对桶进行排序

Offset

默认情况下,bucket键以0开始,然后以interval间隔均匀分布,例如,如果间隔为10,则第一个桶(假设里面有数据)将为[0 - 9],[10-19],[20-29],可以使用offset选项来改变bucket的边界。

这可以用一个例子来说明,如果有10个值从5到14的文档,使用interval10将产生两个bucket,每个bucket包含5个文档,如果使用附加的offset为5,则只有一个包含所有10个文档的单个bucket[5-14]。

Response Format

默认情况下,buckets作为有序数组返回,还可以将响应请求为哈希,而不是用bucket键。

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "prices" : {
  5. "histogram" : {
  6. "field" : "price",
  7. "interval" : 50,
  8. "keyed" : true
  9. }
  10. }
  11. }
  12. }

响应结果:

  1. {
  2. ...
  3. "aggregations": {
  4. "prices": {
  5. "buckets": {
  6. "0.0": {
  7. "key": 0.0,
  8. "doc_count": 1
  9. },
  10. "50.0": {
  11. "key": 50.0,
  12. "doc_count": 1
  13. },
  14. "100.0": {
  15. "key": 100.0,
  16. "doc_count": 0
  17. },
  18. "150.0": {
  19. "key": 150.0,
  20. "doc_count": 2
  21. },
  22. "200.0": {
  23. "key": 200.0,
  24. "doc_count": 3
  25. }
  26. }
  27. }
  28. }
  29. }

Missing value

missing的参数定义了如何处理缺少值的文档,默认情况下,它们将被忽略,但也有可能将它们视为具有值

  1. POST /sales/_search?size=0
  2. {
  3. "aggs" : {
  4. "quantity" : {
  5. "histogram" : {
  6. "field" : "quantity",
  7. "interval": 10,
  8. "missing": 0 1
  9. }
  10. }
  11. }
  12. }

#1 quantity字段没有值的文档将落入与文档相同的bucket中

#1 值为0