Elasticsearch:Top metrics 聚合
2022年11月10日 | by mebius
top_metrics 聚合从文档中选择具有最大或最小排序值的 metrics。 例如,这会获取tgcode文档中 s 字段的最大值所对应的m 字段的值:
POST /test/_bulk?refresh
{"index":{}}
{"s":1,"m":3.1415}
{"index":{}}
{"s":2,"m":1}
{"index":{}}
{"s":3,"m":2.71828}
POST /test/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": {
"metrics": {
"field": "m"
},
"sort": {
"s": "desc"
}
}
}
}
}
上面的聚合返回的结果是:
{
"aggregations": {
"tm": {
"top": [
{
"sort": [
3
],
"metrics": {
"m": 2.718280076980591
}
}
]
}
}
}
s 字段的最大值为 3,而它对应的 m 值为2.718280076980591。
top_metrics 在本质上与 top_hits 非常相似,但由于它受到更多限制,它能够使用更少的内存来完成它的工作,并且通常更快。
sort
metric 请求中的 sort 字段的功能与 search 请求中的 sort 字段完全相同,除了:
聚合返回的 metric 是搜索请求将返回的第一个命中。 所以,
“sort”: {“s”: “desc”}
从具有最大s 值的文档中获取 metric
“sort”: {“s”: “asc”}
从具有最小s 值的文档中获取 metric
“sort”: {“_geo_distance”: {“location”: “POINT (-78.6382 35.7796)”}}
位置最接近 35.7796, -78.6382 的文档中获取 metric
“sort”: “_score”
从得分最高的文档中获取 metric
metrics
metrics 选择要返回的 top 文档的字段。 你可以通过请求像 “metrics”: [{“field”: “m”} 或者以 "metrics": [{"field": "m"}, {"field": "i"} 的形式请求
多个 metrics。metrics.field 支持如下的字段类型:
除 keywords 外,还支持对应类型的运行时字段(runtime fields)。 metrtgcodeics.field 不支持具有数组值的字段。 数组值的 top_metric 聚合可能会返回不一致的结果。
以下示例对几种字段类型运行 top_metrics 聚合。
DELETE test
PUT /test
{
"mappings": {
"properties": {
"d": {
"type": "date"
}
}
}
}
POST /test/_bulk?refresh
{"index":{}}
{"s":1,"m":3.1415,"i":1,"d":"2020-01-01T00:12:12Z","t":"cat"}
{"index":{}}
{"s":2,"m":1,"i":6,"d":"2020-01-02T00:12:12Z","t":"dog"}
{"index":{}}
{"s":3,"m":2.71828,"i":-12,"d":"2019-12-31T00:12:12Z","t":"chicken"}
POST /test/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": {
"metrics": [
{"field": "m"},
{"field": "i"},
{"field": "d"},
{"field": "t.keyword"}
],
"sort": {"s": "desc"}
}
}
}
}
上面的聚合返回结果:
{
"aggregations": {
"tm": {
"top": [
{
"sort": [
3
],
"metrics": {
"m": 2.718280076980591,
"i": -12,
"d": "2019-12-31T00:12:12.000Z",
"t.keyword": "chicken"
}
}
]
}
}
}
size
top_metrics 可以使用 size 参数返回前几个文档的 metrics 值:
DELETE test
POST /test/_bulk?refresh
{"index": {}}
{"s": 1, "m": 3.1415}
{"index": {}}
{"s": 2, "m": 1.0}
{"index": {}}
{"s": 3, "m": 2.71828}
POST /test/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": {
"metrics": {
"field": "m"
},
"sort": {
"s": "desc"
},
"size": 3
}
}
}
}
上面的聚合返回:
{
"aggregations": {
"tm": {
"top": [
{
"sort": [
3
],
"metrics": {
"m": 2.718280076980591
}
},
{
"sort": [
2
],
"metrics": {
"m": 1
}
},
{
"sort": [
1
],
"metrics": {
"m": 3.1414999961853027
}
}
]
}
}
}
默认大小为 1。最大默认大小为 10,因为聚合的工作存储是“密集”的,这意味着我们为每个存储桶分配大小槽。 10 是一个非常保守的默认最大值,如果需要,可以通过更改 top_metrics_max_size 索引设置来提高它。 但是要知道,大尺寸可能会占用相当多的内存,特别是如果它们位于聚合内部,这会使许多存储桶像大 terms aggregation一样。 如果你想提高它,请使用以下内容:
PUT /test/_settings
{
"top_metrics_max_size": 100
}
注意:如果 size 大于 1,则 top_metrics 聚合不能成为排序的目标。
示例
和 terms 一起使用
这种聚合在 terms 聚合中应该非常有用,例如,查找每个服务器报告的最后一个值。
PUT /node
{
"mappings": {
"properties": {
"ip": {"type": "ip"},
"date": {"type": "date"}
}
}
}
POST /node/_bulk?refresh
{"index":{}}
{"ip":"192.168.0.1","date":"2020-01-01T01:01:01","m":1}
{"index":{}}
{"ip":"192.168.0.1","date":"2020-01-01T02:01:01","m":2}
{"index":{}}
{"ip":"192.168.0.2","date":"2020-01-01T02:01:01","m":3}
POST /node/_search?filter_path=aggregations
{
"aggs": {
"ip": {
"terms": {
"field": "ip"
},
"aggs": {
"tm": {
"top_metrics": {
"metrics": {
"field": "m"
},
"sort": {
"date": "desc"
}
}
}
}
}
}
}
上面的聚合返回:
{
"aggregations": {
"ip": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "192.168.0.1",
"doc_count": 2,
"tm": {
"top": [
{
"sort": [
"2020-01-01T02:01:01.000Z"
],
"metrics": {
"m": 2
}
}
]
}
},
{
"key": "192.168.0.2",
"doc_count": 1,
"tm": {
"top": [
{
"sort": [
tgcode "2020-01-01T02:01:01.000Z"
],
"metrics": {
"m": 3
}
}
]
}
}
]
}
}
}
与 top_hits 不同,你可以按此指标的结果对存储桶进行排序:
POST /node/_search?filter_path=aggregations
{
"aggs": {
"ip": {
"terms": {
"field": "ip",
"order": {"tm.m": "desc"}
},
"aggs": {
"tm": {
"top_metrics": {
"metrics": {"field": "m"},
"sort": {"date": "desc"}
}
}
}
}
}
}
上面的结果显示:
{
"aggregations": {
"ip": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "192.168.0.2",
"doc_count": 1,
"tm": {
"top": [
{
"sort": [
"2020-01-01T02:01:01.000Z"
],
"metrics": {
"m": 3
}
}
]
}
},
{
"key": "192.168.0.1",
"doc_count": 2,
"tm": {
"top": [
{
"sort": [
"2020-01-01T02:01:01.000Z"
],
"metrics": {
"m": 2
}
}
]
}
}
]
}
}
}
混合排序类型
按跨不同索引的不同类型的字段对 top_metrics 进行排序会产生一些令人惊讶的结果:浮点字段总是独立于整数字段进行排序。
DELETE test
POST /test/_bulk?refresh
{"index":{"_index":"test1"}}
{"s":1,"m":3.1415}
{"index":{"_index":"test1"}}
{"s":2,"m":1}
{"index":{"_index":"test2"}}
{"s":3.1,"m":2.71828}
POST /test*/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": {
"metrics": {
"field": "m"
},
"sort": {
"s": "asc"
}
}
}
}
}
上面的聚合返回结果:
{
"aggregations": {
"tm": {
"top": [
{
"sort": [
3.0999999046325684
],
"metrics": {
"m": 2.718280076980591
}
}
]
}
}
}
虽然这比错误要好,但它可能不是你想要的。 虽然它确实会丢失一些精度,但你可以使用以下方式将整数字段显式转换为浮点数:
POST /test*/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": {
"metrics": {
"field": "m"
},
"sort": {
"s": {
"order": "asc",
"numeric_type": "double"
}
}
}
}
}
}
上面的聚合结果显示:
{
"aggregations": {
"tm": {
"top": [
{
"sort": [
1
],
"metrics": {
"m": 3.1414999961853027
}
}
]
}
}
}
参考:
【1】Top metrics aggregation | Elasticsearch Guide [8.4] | Elastic
文章来源于互联网:Elasticsearch:Top metrics 聚合