# Histogram Aggregation

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

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

贡献者 : @于永超，[ApacheCN](/display/~apachecn)，[Apache中文网](/display/~apachechina)

## Histogram Aggregation

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

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

```

interval必须是正数，而offset（偏移量）必须是小数`[0, interval[`.

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

```
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
                }
            ]
        }
    }
}
```

### Minimum document count

上面的结果显示，没有任何文档的价格在[100 - 150)范围内。默认情况下，返回结果将用空桶填充直方图中的空白。由于min_doc_count设置，可能会更改这个和请求桶的最小值，这是由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返回数据本身范围内的所有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设置将范围过滤器聚合下的直方图聚合嵌套。

例子：

```
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
                }
            }
        }
    }
}
```

### Order

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

按键降序排列桶：

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

按其doc_count - 升序排列：

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

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

```
POST /sales/_search?size=0
{
    "aggs" : {
        "prices" : {
            "histogram" : {
                "field" : "price",
                "interval" : 50,
                "order" : { "price_stats.min" : "asc" } #1
            },
            "aggs" : {
                "price_stats" : { "stats" : {"field" : "price"} }
            }
        }
    }
}
```

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

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

```
AGG_SEPARATOR       =  '>' ;
METRIC_SEPARATOR    =  '.' ;
AGG_NAME            =  <the name of the aggregation> ;
METRIC              =  <the name of the metric (in case of multi-value metrics aggregation)> ;
PATH                =  <AGG_NAME> [ <AGG_SEPARATOR>, <AGG_NAME> ]* [ <METRIC_SEPARATOR>, <METRIC> ] ;
```

```
POST /sales/_search?size=0
{
    "aggs" : {
        "prices" : {
            "histogram" : {
                "field" : "price",
                "interval" : 50,
                "order" : { "promoted_products>rating_stats.avg" : "desc" } 
            },
            "aggs" : {
                "promoted_products" : {
                    "filter" : { "term" : { "promoted" : true }},
                    "aggs" : {
                        "rating_stats" : { "stats" : { "field" : "rating" }}
                    }
                }
            }
        }
    }
}
```

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

### 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键。

```
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 value

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

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

```

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

＃1   值为0