跳到主要内容

复合聚合 composite

Composite Aggregation

从不同来源创建复合桶的多桶聚合。

与其他多桶聚合不同,复合聚合可用于高效地对多级聚合中的所有桶进行分页。这种聚合提供了一种方式来流化特定聚合的所有桶,类似于滚动对文档所做的操作。

composite buckets 是根据为每个文档 extracted/created 的值的组合构建的,每个组合都被视为composite bucket。

例如,以下文件

{
"keyword": ["foo", "bar"],
"number": [23, 65, 76]
}

…当keywordnumber用作聚合的value source时,将创建以下复合桶:

{ "keyword": "foo", "number": 23 }
{ "keyword": "foo", "number": 65 }
{ "keyword": "foo", "number": 76 }
{ "keyword": "bar", "number": 23 }
{ "keyword": "bar", "number": 65 }
{ "keyword": "bar", "number": 76 }

Values source

sources参数控制应用于构建复合存储桶的源。有三种不同类型的values source:

Terms

terms value source 相当于一个简单的terms aggregation。这些值是从字段或脚本中提取的,与 terms aggregation 完全相同。

例子

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "product": { "terms" : { "field": "product" } } }
]
}
}
}
}

与terms aggregation类似,也可以使用脚本创建复合桶的值:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{
"product": {
"terms" : {
"script" : {
"source": "doc['product'].value",
"lang": "painless"
}
}
}
}
]
}
}
}
}

Histogram

Histogram value source 可以应用于数值,以在数值上建立固定大小的间隔。interval参数定义如何转换数值。例如,设置为5的间隔将将任何数值转换为其最近的间隔,值101将转换为100,这是100和105之间的间隔的关键

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "histo": { "histogram" : { "field": "price", "interval": 5 } } }
]
}
}
}
}

这些值是从返回数值的数值字段或脚本生成的:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{
"histo": {
"histogram" : {
"interval": 5,
"script" : {
"source": "doc['price'].value",
"lang": "painless"
}
}
}
}
]
}
}
}
}

Date Histogram

date_histogram与histogram value source相似,只是间隔由日期/时间表达式指定:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "date": { "date_histogram" : { "field": "timestamp", "interval": "1d" } } }
]
}
}
}
}

上面的示例每天创建一个间隔,并将所有时间戳值转换为最近间隔的开始。间隔的可用表达式:year, quarter, month, week, day, hour, minute, second

时间值也可以通过时间单位解析支持的缩写来指定。请注意,不支持分数时间值,但您可以通过转换到另一个时间单位(例如,可以将1.5h指定为90m)来解决此问题。

Format

在内部,日期表示为64位数字,表示自纪元以来的时间戳(以毫秒为单位)。这些时间戳作为bucket key返回。可以使用format参数指定的格式返回格式化的日期字符串:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{
"date": {
"date_histogram" : {
"field": "timestamp",
"interval": "1d",
"format": "yyyy-MM-dd"
}
}
}
]
}
}
}
}

Time Zone

日期时间以UTC格式存储在Elasticsearch中。time_zone参数可用于指示分组应使用不同的时区。

时区可以指定为ISO 8601 UTC偏移量(例如+01:00或-08:00),也可以指定为时区id,这是TZ数据库中使用的标识符,如America/Loss_Angeles。

Mixing different values source

sources参数接受value source的数组。可以混合不同的value来创建复合桶。例如:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "date": { "date_histogram": { "field": "timestamp", "interval": "1d" } } },
{ "product": { "terms": {"field": "product" } } }
]
}
}
}
}

这将从两个value source(date_histogram和terms)创建的值创建复合桶。每个存储桶由两个值组成,一个用于聚合中定义的每个value source。允许任何类型的组合,数组中的顺序保留在组合桶中。

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "shop": { "terms": {"field": "shop" } } },
{ "product": { "terms": { "field": "product" } } },
{ "date": { "date_histogram": { "field": "timestamp", "interval": "1d" } } }
]
}
}
}
}

Order

默认情况下,复合桶按其自然顺序排序。值按其值的升序排序。当请求多个value source时,对每个value source进行排序,将组合桶的第一个值与另一个组合桶的第二个值进行比较,如果它们相等,则组合桶中的下一个值将用于断开连接。这意味着复合桶[foo,100]被认为小于[foobar,0],因为foo被认为小于foobar。通过直接在value source定义中将顺序设置为asc(默认值)或desc(降序),可以定义每个value source的排序方向。例如:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "date": { "date_histogram": { "field": "timestamp", "interval": "1d", "order": "desc" } } },
{ "product": { "terms": {"field": "product", "order": "asc" } } }
]
}
}
}
}

…将在比较date_histogram源中的值时按降序对复合存储桶进行排序,在比较术语源中的数值时按升序对复合存储。

Missing bucket

默认情况下,忽略没有给定source value的文档。通过将missing_bucket设置为true(默认为false),可以将它们包含在响应中:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "product_name": { "terms" : { "field": "product", "missing_bucket": true } } }
]
}
}
}
}

在上面的示例中, source product_name将为当product字段为空值的文档指定显示的null值,。order 决定了空值应该排在第一位(升序,asc)还是最后一位(降序,desc)。

Size

可以设置size参数来定义应该返回多少复合桶。每个复合桶被视为单个桶,因此将大小设置为10将返回从value source创建的前10个复合桶。响应包含数组中每个复合存储桶的值,该数组包含从每个value source提取的值。

After

如果复合桶的数量太多(或未知),无法在单个响应中返回,则可以将检索拆分为多个请求。由于复合桶本质上是平的,因此请求的大小正好是将在响应中返回的复合桶的数量(假设它们至少是要返回的大小的复合桶)。如果应该检索所有复合桶,最好使用较小的大小(例如100或1000),然后使用after参数检索下一个结果。例如:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"size": 2,
"sources" : [
{ "date": { "date_histogram": { "field": "timestamp", "interval": "1d" } } },
{ "product": { "terms": {"field": "product" } } }
]
}
}
}
}

返回

{
...
"aggregations": {
"my_buckets": {
"after_key": {
"date": 1494288000000,
"product": "mad max"
},
"buckets": [
{
"key": {
"date": 1494201600000,
"product": "rocky"
},
"doc_count": 1
},
{
"key": {
"date": 1494288000000,
"product": "mad max"
},
"doc_count": 2
}
]
}
}
}

after_key等于响应中返回的最后一个bucket,该bucket是管道聚合进行任何过滤之前返回的。如果管道聚合过滤/删除了所有桶,after_key将包含过滤前的最后一个桶。

after参数可用于检索上一轮返回的最后一个复合存储桶之后的复合存储桶。对于下面的示例,最后一个桶可以在after_key中找到,下一轮结果可以通过以下方式检索:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"size": 2,
"sources" : [
{ "date": { "date_histogram": { "field": "timestamp", "interval": "1d", "order": "desc" } } },
{ "product": { "terms": {"field": "product", "order": "asc" } } }
],
"after": { "date": 1494288000000, "product": "mad max" }
}
}
}
}

Sub-aggregations

与任何多桶聚合一样,复合聚合可以包含子聚合。这些子聚合可用于计算其他存储桶或此父聚合创建的每个复合存储桶的统计信息。例如,以下示例计算每个复合存储桶的字段平均值:

GET /_search
{
"aggs" : {
"my_buckets": {
"composite" : {
"sources" : [
{ "date": { "date_histogram": { "field": "timestamp", "interval": "1d", "order": "desc" } } },
{ "product": { "terms": {"field": "product" } } }
]
},
"aggregations": {
"the_avg": {
"avg": { "field": "price" }
}
}
}
}
}

返回

{
...
"aggregations": {
"my_buckets": {
"after_key": {
"date": 1494201600000,
"product": "rocky"
},
"buckets": [
{
"key": {
"date": 1494460800000,
"product": "apocalypse now"
},
"doc_count": 1,
"the_avg": {
"value": 10.0
}
},
{
"key": {
"date": 1494374400000,
"product": "mad max"
},
"doc_count": 1,
"the_avg": {
"value": 27.0
}
},
{
"key": {
"date": 1494288000000,
"product" : "mad max"
},
"doc_count": 2,
"the_avg": {
"value": 22.5
}
},
{
"key": {
"date": 1494201600000,
"product": "rocky"
},
"doc_count": 1,
"the_avg": {
"value": 10.0
}
}
]
}
}
}