top_metrics 聚合从文档中挑选具有最大或最小 “排序” 值的指标。 例如,这会获取文档中 s 字段的最大值所对应的m 字段的值:

`
1.  POST /test/_bulk?refresh
2.  {"index":{}}
3.  {"s":1,"m":3.1415}
4.  {"index":{}}
5.  {"s":2,"m":1}
6.  {"index":{}}
7.  {"s":3,"m":2.71828}
10.  POST /test/_search?filter_path=aggregations
11.  {
12.    "aggs": {
13.      "tm": {
14.        "top_metrics": {
15.          "metrics": {
16.            "field": "m"
17.          },
18.          "sort": {
19.            "s": "desc"
20.          }
21.        }
22.      }
23.    }
24.  }
`![]()

上面的聚合回来的成果是:

`
1.  {
2.    "aggregations": {
3.      "tm": {
4.        "top": [
5.          {
6.            "sort": [
7.              3
8.            ],
9.            "metrics": {
10.              "m": 2.718280076980591
11.            }
12.          }
13.        ]
14.      }
15.    }
16.  }
`![]()

s 字段的最多值为 3,而它对应的 m 值为2.718280076980591。

top_metrics 在本质上与 top_hits 十分相似,但由于它遭到更多限制,它能够运用更少的内存来完成它的作业,而且一般更快。

sort

metric 恳求中的 sort 字段的功能与 search 恳求中的 sort 字段完全相同,除了:

  • 它不能用于 binary、flattened、ip、keyword 或 text 字段。
  • 它仅支撑单个排序值,因此未指定哪个文档胜出。

聚合回来的 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 支撑如下的字段类型:

  • boolean
  • ip
  • keywords
  • numbers

除 keywords 外,还支撑对应类型的运行时字段(runtime fields)。 metrics.field 不支撑具有数组值的字段。 数组值的 top_metric 聚合可能会回来不一致的成果。

以下示例对几种字段类型运行 top_metrics 聚合。


1.  DELETE test
2.  PUT /test
3.  {
4.    "mappings": {
5.      "properties": {
6.        "d": {
7.          "type": "date"
8.        }
9.      }
10.    }
11.  }

1.  POST /test/_bulk?refresh
2.  {"index":{}}
3.  {"s":1,"m":3.1415,"i":1,"d":"2020-01-01T00:12:12Z","t":"cat"}
4.  {"index":{}}
5.  {"s":2,"m":1,"i":6,"d":"2020-01-02T00:12:12Z","t":"dog"}
6.  {"index":{}}
7.  {"s":3,"m":2.71828,"i":-12,"d":"2019-12-31T00:12:12Z","t":"chicken"}
`
1.  POST /test/_search?filter_path=aggregations
2.  {
3.    "aggs": {
4.      "tm": {
5.        "top_metrics": {
6.          "metrics": [
7.            {"field": "m"},
8.            {"field": "i"},
9.            {"field": "d"},
10.            {"field": "t.keyword"}
11.          ],
12.          "sort": {"s": "desc"}
13.        }
14.      }
15.    }
16.  }
`![]()

上面的聚合回来成果:

`
1.  {
2.    "aggregations": {
3.      "tm": {
4.        "top": [
5.          {
6.            "sort": [
7.              3
8.            ],
9.            "metrics": {
10.              "m": 2.718280076980591,
11.              "i": -12,
12.              "d": "2019-12-31T00:12:12.000Z",
13.              "t.keyword": "chicken"
14.            }
15.          }
16.        ]
17.      }
18.    }
19.  }
`![]()

size

top_metrics 能够运用 size 参数回来前几个文档的 metrics 值:


1.  DELETE test
2.  POST /test/_bulk?refresh
3.  {"index": {}}
4.  {"s": 1, "m": 3.1415}
5.  {"index": {}}
6.  {"s": 2, "m": 1.0}
7.  {"index": {}}
8.  {"s": 3, "m": 2.71828}
`
1.  POST /test/_search?filter_path=aggregations
2.  {
3.    "aggs": {
4.      "tm": {
5.        "top_metrics": {
6.          "metrics": {
7.            "field": "m"
8.          },
9.          "sort": {
10.            "s": "desc"
11.          },
12.          "size": 3
13.        }
14.      }
15.    }
16.  }
`![]()

上面的聚合回来:

`
1.  {
2.    "aggregations": {
3.      "tm": {
4.        "top": [
5.          {
6.            "sort": [
7.              3
8.            ],
9.            "metrics": {
10.              "m": 2.718280076980591
11.            }
12.          },
13.          {
14.            "sort": [
15.              2
16.            ],
17.            "metrics": {
18.              "m": 1
19.            }
20.          },
21.          {
22.            "sort": [
23.              1
24.            ],
25.            "metrics": {
26.              "m": 3.1414999961853027
27.            }
28.          }
29.        ]
30.      }
31.    }
32.  }
`![]()

默许巨细为 1。最大默许巨细为 10,因为聚合的作业存储是“密布”的,这意味着咱们为每个存储桶分配巨细槽。 10 是一个十分保存的默许最大值,假如需求,能够经过更改 top_metrics_max_size 索引设置来进步它。 但是要知道,大尺寸可能会占用相当多的内存,特别是假如它们位于聚合内部,这会使许多存储桶像大 terms aggregation相同。 假如你想进步它,请运用以下内容:


1.  PUT /test/_settings
2.  {
3.    "top_metrics_max_size": 100
4.  }

注意:假如 size 大于 1,则 top_metrics 聚合不能成为排序的方针。

示例

和 terms 一同运用

这种聚合在 terms 聚合中应该十分有用,例如,查找每个服务器陈述的最终一个值。


1.  PUT /node
2.  {
3.    "mappings": {
4.      "properties": {
5.        "ip": {"type": "ip"},
6.        "date": {"type": "date"}
7.      }
8.    }
9.  }

1.  POST /node/_bulk?refresh
2.  {"index":{}}
3.  {"ip":"192.168.0.1","date":"2020-01-01T01:01:01","m":1}
4.  {"index":{}}
5.  {"ip":"192.168.0.1","date":"2020-01-01T02:01:01","m":2}
6.  {"index":{}}
7.  {"ip":"192.168.0.2","date":"2020-01-01T02:01:01","m":3}
`
1.  POST /node/_search?filter_path=aggregations
2.  {
3.    "aggs": {
4.      "ip": {
5.        "terms": {
6.          "field": "ip"
7.        },
8.        "aggs": {
9.          "tm": {
10.            "top_metrics": {
11.              "metrics": {
12.                "field": "m"
13.              },
14.              "sort": {
15.                "date": "desc"
16.              }
17.            }
18.          }
19.        }
20.      }
21.    }
22.  }
`![]()

上面的聚合回来:

`
1.  {
2.    "aggregations": {
3.      "ip": {
4.        "doc_count_error_upper_bound": 0,
5.        "sum_other_doc_count": 0,
6.        "buckets": [
7.          {
8.            "key": "192.168.0.1",
9.            "doc_count": 2,
10.            "tm": {
11.              "top": [
12.                {
13.                  "sort": [
14.                    "2020-01-01T02:01:01.000Z"
15.                  ],
16.                  "metrics": {
17.                    "m": 2
18.                  }
19.                }
20.              ]
21.            }
22.          },
23.          {
24.            "key": "192.168.0.2",
25.            "doc_count": 1,
26.            "tm": {
27.              "top": [
28.                {
29.                  "sort": [
30.                    "2020-01-01T02:01:01.000Z"
31.                  ],
32.                  "metrics": {
33.                    "m": 3
34.                  }
35.                }
36.              ]
37.            }
38.          }
39.        ]
40.      }
41.    }
42.  }
`![]()

与 top_hits 不同,你能够按此指标的成果对存储桶进行排序:

`
1.  POST /node/_search?filter_path=aggregations
2.  {
3.    "aggs": {
4.      "ip": {
5.        "terms": {
6.          "field": "ip",
7.          "order": {"tm.m": "desc"}
8.        },
9.        "aggs": {
10.          "tm": {
11.            "top_metrics": {
12.              "metrics": {"field": "m"},
13.              "sort": {"date": "desc"}
14.            }
15.          }
16.        }
17.      }
18.    }
19.  }
`![]()

上面的成果显示:

`
1.  {
2.    "aggregations": {
3.      "ip": {
4.        "doc_count_error_upper_bound": 0,
5.        "sum_other_doc_count": 0,
6.        "buckets": [
7.          {
8.            "key": "192.168.0.2",
9.            "doc_count": 1,
10.            "tm": {
11.              "top": [
12.                {
13.                  "sort": [
14.                    "2020-01-01T02:01:01.000Z"
15.                  ],
16.                  "metrics": {
17.                    "m": 3
18.                  }
19.                }
20.              ]
21.            }
22.          },
23.          {
24.            "key": "192.168.0.1",
25.            "doc_count": 2,
26.            "tm": {
27.              "top": [
28.                {
29.                  "sort": [
30.                    "2020-01-01T02:01:01.000Z"
31.                  ],
32.                  "metrics": {
33.                    "m": 2
34.                  }
35.                }
36.              ]
37.            }
38.          }
39.        ]
40.      }
41.    }
42.  }
`![]()

混合排序类型

按跨不同索引的不同类型的字段对 top_metrics 进行排序会产生一些令人惊讶的成果:浮点字段总是独立于整数字段进行排序。


1.  DELETE test
2.  POST /test/_bulk?refresh
3.  {"index":{"_index":"test1"}}
4.  {"s":1,"m":3.1415}
5.  {"index":{"_index":"test1"}}
6.  {"s":2,"m":1}
7.  {"index":{"_index":"test2"}}
8.  {"s":3.1,"m":2.71828}
`
1.  POST /test*/_search?filter_path=aggregations
2.  {
3.    "aggs": {
4.      "tm": {
5.        "top_metrics": {
6.          "metrics": {
7.            "field": "m"
8.          },
9.          "sort": {
10.            "s": "asc"
11.          }
12.        }
13.      }
14.    }
15.  }
`![]()

上面的聚合回来成果:

`
1.  {
2.    "aggregations": {
3.      "tm": {
4.        "top": [
5.          {
6.            "sort": [
7.              3.0999999046325684
8.            ],
9.            "metrics": {
10.              "m": 2.718280076980591
11.            }
12.          }
13.        ]
14.      }
15.    }
16.  }
`![]()

尽管这比错误要好,但它可能不是你想要的。 尽管它的确会丢失一些精度,但你能够运用以下方式将整数字段显式转换为浮点数:

`
1.  POST /test*/_search?filter_path=aggregations
2.  {
3.    "aggs": {
4.      "tm": {
5.        "top_metrics": {
6.          "metrics": {
7.            "field": "m"
8.          },
9.          "sort": {
10.            "s": {
11.              "order": "asc",
12.              "numeric_type": "double"
13.            }
14.          }
15.        }
16.      }
17.    }
18.  }
`![]()

上面的聚合成果显示:

`
1.  {
2.    "aggregations": {
3.      "tm": {
4.        "top": [
5.          {
6.            "sort": [
7.              1
8.            ],
9.            "metrics": {
10.              "m": 3.1414999961853027
11.            }
12.          }
13.        ]
14.      }
15.    }
16.  }
`![]()

参考:

【1】Top metrics aggregation | Elasticsearch Guide [8.4] | Elastic