聚合的用例各异,从实时分析数据以采取某些行动,到使用OpenSearch仪表板创建可视化仪表板。
OpenSearch可以在毫秒内对大规模数据集执行聚合。与查询相比,聚合消耗更多的CPU周期和内存。
先来个总结表格:
聚合类型 | Elasticsearch | SQL |
---|---|---|
指标聚合(Metric Aggregations) | ||
平均值(Average) | avg | SELECT AVG(column) FROM table; |
基数(Cardinality) | cardinality | SELECT COUNT(DISTINCT column) FROM table; |
扩展统计(Extended Stats) | extended_stats | SELECT AVG(column), MIN(column), MAX(column), COUNT(column) FROM table; |
地理边界(Geobounds) | geobounds | 无SQL对应,用于地理坐标范围的统计。 |
矩阵统计(Matrix Stats) | matrix_stats | 无SQL对应,用于多值字段的统计。 |
最大值(Maximum) | max | SELECT MAX(column) FROM table; |
最小值(Minimum) | min | SELECT MIN(column) FROM table; |
百分位排名(Percentile Ranks) | percentiles_rank | SELECT PERCENTILE_CONT(percentage) WITHIN GROUP (ORDER BY column) FROM table; |
百分位(Percentile) | percentiles | SELECT PERCENTILE_CONT(percentage) WITHIN GROUP (ORDER BY column) FROM table; |
脚本度量(Scripted Metric) | scripted_metric | 无SQL对应,通过自定义脚本计算度量。 |
统计信息(Stats) | stats | SELECT AVG(column), MIN(column), MAX(column), COUNT(column), SUM(column) FROM table; |
求和(Sum) | sum | SELECT SUM(column) FROM table; |
前N条记录(Top Hits) | top_hits | 无SQL对应,返回每个桶中排序后的前N条记录。 |
值计数(Value Count) | value_count | SELECT COUNT(column) FROM table; |
桶聚合(Bucket Aggregations) | Elasticsearch | SQL |
---|---|---|
邻接矩阵(Adjacency Matrix) | adjacency_matrix | 无SQL对应,用于关系型数据的统计。 |
日期直方图(Date Histogram) | date_histogram | SELECT COUNT(column), DATE_TRUNC('interval', date_column) FROM table GROUP BY DATE_TRUNC('interval', date_column); |
日期范围(Date Range) | date_range | SELECT COUNT(column) FROM table WHERE date_column BETWEEN start_date AND end_date; |
多样化采样(Diversified Sampler) | diversified_sampler | 无SQL对应,用于多样本的统计。 |
过滤器(Filter) | filter | SELECT COUNT(column) FROM table WHERE condition; |
多过滤器(Filters) | filters | 无SQL对应,用于同时应用多个过滤器的统计。 |
地理距离(Geodistance) | geodistance | 无SQL对应,用于地理坐标距离的统计。 |
地理哈希网格(Geohash Grid) | geohash_grid | 无SQL对应,用于地理坐标哈希网格的统计。 |
地理六边形网格(Geohex Grid) | geohex_grid | 无SQL对应,用于地理坐标六边形网格的统计。 |
地理瓦片网格(Geotile Grid) | geotile_grid | 无SQL对应,用于地理坐标瓦片网格的统计。 |
全局(Global) | global | 无SQL对应,用于对整个数据集执行聚合而不分组。 |
直方图(Histogram) | histogram | SELECT COUNT(column), FLOOR(column/interval)*interval as range FROM table GROUP BY range; |
IP范围(IP Range) | ip_range | 无SQL对应,用于IP地址范围的统计。 |
缺失值(Missing) | missing | SELECT COUNT(column) FROM table WHERE column IS NULL; |
多词项(Multi-terms) | multi_terms | 无SQL对应,用于多个词项的统计。 |
嵌套(Nested) | nested | 无SQL对应,用于嵌套文档的统计。 |
范围(Range) | range | SELECT COUNT(column) FROM table WHERE column BETWEEN min AND max; |
反向嵌套(Reverse Nested) | reverse_nested | 无SQL对应,用于反向嵌套文档的统计。 |
采样器(Sampler) | sampler | 无SQL对应,用于对样本进行统计。 |
显著项(Significant Terms) | significant_terms | 无SQL对应,用于显著项的统计。 |
显著文本(Significant Text) | significant_text | 无SQL对应,用于显著文本的统计。 |
词项(Terms) | terms | SELECT COUNT(column) FROM table GROUP BY column; |
默认情况下,OpenSearch不支持在文本字段上进行聚合。因为文本字段被标记化,对文本字段的聚合必须将标记化过程反转回其原始字符串,然后基于此进行聚合。这种操作消耗大量内存并降低集群性能。
虽然您可以通过在映射中将 fielddata
参数设置为 true
来启用文本字段的聚合,但聚合仍然基于标记化单词而不是原始文本。
我们建议将文本字段的原始版本保留为可聚合的 keyword
字段。
在这种情况下,您可以对 title.raw
字段而不是 title
字段执行聚合:
PUT movies
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fielddata": true,
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
聚合查询的结构如下:
GET _search
{
"size": 0,
"aggs": {
"NAME": {
"AGG_TYPE": {}
}
}
}
如果您只对聚合结果感兴趣而不对查询结果感兴趣,请将 size
设置为 0。
在 aggs
属性中(如果需要,可以使用 aggregations
),您可以定义任意数量的聚合。每个聚合均由其名称和 OpenSearch 支持的聚合类型之一定义。
聚合的名称可帮助您区分响应中的不同聚合。 AGG_TYPE
属性是您指定聚合类型的位置。
聚合内的聚合称为嵌套聚合或子聚合。
指标聚合产生简单的结果,并且不能包含嵌套聚合。
存储桶聚合生成可以嵌套在其他聚合中的文档存储桶。您可以通过在存储桶聚合中嵌套指标和存储桶聚合来对数据执行复杂的分析。
通用嵌套聚合语法
{
"aggs": {
"name": {
"type": {
"data"
},
"aggs": {
"nested": {
"type": {
"data"
}
}
}
}
}
}
内部 aggs
关键字开始新的嵌套聚合。父聚合和嵌套聚合的语法相同。嵌套聚合在前面的父聚合的上下文中运行。
您还可以将聚合与搜索查询配对,以缩小聚合之前尝试分析的范围。如果您不添加查询,OpenSearch 会隐式使用 match_all
查询。
由于聚合器对所有值都使用 double
数据类型进行处理,因此 2 53 及更大的 long
值是近似值。
聚合主要分为三种类型:
sum
、 min
、 max
和 avg
。指标聚合可让您执行简单的计算,例如查找字段的最小值、最大值和平均值。
度量聚合有两种类型:单值度量聚合和多值度量聚合。
sum
、 min
、 max
、 avg
、 cardinality
。stats
、 extended_stats
、 matrix_stats
、 percentile
、 percentile_ranks
、 geo_bound
、 top_hits
和 scripted_metric
。要查找 taxful_total_price
字段的平均值:
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"avg_taxful_total_price": { // 这个名字可以随意定义
"avg": { // 求平均值
"field": "taxful_total_price" // 在taxful_total_price字段上 操作
}
}
}
}
响应示例
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4675,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"avg_taxful_total_price" : { // 呼应前面定义的名称
"value" : 75.05542864304813
}
}
}
cardinality
指标是单值指标聚合,用于计算字段的唯一或不同值的数量。
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"unique_products": {
"cardinality": {
"field": "products.product_id"
}
}
}
}
...
"aggregations" : {
"unique_products" : {
"value" : 7033
}
}
}
基数计数是近似值。如果您的假设商店中有数万种产品,则准确的基数计算需要将所有值加载到哈希集中并返回其大小。这种方法的扩展性不好;它需要大量内存并可能导致高延迟。
您可以使用 precision_threshold
设置来控制内存和准确性之间的权衡。此设置定义阈值,低于该阈值计数预计接近准确。高于此值,计数可能会变得不太准确。 precision_threshold
的默认值为 3,000。支持的最大值为 40,000。
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"unique_products": {
"cardinality": {
"field": "products.product_id",
"precision_threshold": 10000
}
}
}
}
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"percentile_taxful_total_price": {
"percentiles": {
"field": "taxful_total_price"
}
}
}
}
...
"aggregations" : {
"percentile_taxful_total_price" : {
"values" : {
"1.0" : 21.984375,
"5.0" : 27.984375,
"25.0" : 44.96875,
"50.0" : 64.22061688311689,
"75.0" : 93.0,
"95.0" : 156.0,
"99.0" : 222.0
}
}
}
}
stats
指标是一个多值指标聚合,它返回所有基本指标,例如 min
、 max
、 sum
、 avg
和 value_count
在一个聚合查询中。
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"stats_taxful_total_price": {
"stats": {
"field": "taxful_total_price"
}
}
}
}
...
"aggregations" : {
"stats_taxful_total_price" : {
"count" : 4675,
"min" : 6.98828125,
"max" : 2250.0,
"avg" : 75.05542864304813,
"sum" : 350884.12890625
}
}
}
top_hits
指标是一种多值指标聚合,它根据正在聚合的字段的相关性得分对匹配文档进行排名。
from
:命中的起始位置。
size
:返回的最大命中数。默认值为 3。
sort
:匹配的命中如何排序。默认情况下,命中按聚合查询的相关性分数排序。
以下示例返回电子商务数据中排名前 5 的产品:
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"top_hits_products": {
"top_hits": {
"size": 5
}
}
}
}
...
"aggregations" : {
"top_hits_products" : {
"hits" : {
"total" : {
"value" : 4675,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "opensearch_dashboards_sample_data_ecommerce",
"_type" : "_doc",
"_id" : "glMlwXcBQVLeQPrkHPtI",
"_score" : 1.0,
"_source" : {
"category" : [
"Women's Accessories",
"Women's Clothing"
],
"currency" : "EUR",
"customer_first_name" : "rania",
"customer_full_name" : "rania Evans",
"customer_gender" : "FEMALE",
"customer_id" : 24,
"customer_last_name" : "Evans",
"customer_phone" : "",
"day_of_week" : "Sunday",
"day_of_week_i" : 6,
"email" : "rania@evans-family.zzz",
"manufacturer" : [
"Tigress Enterprises"
],
"order_date" : "2021-02-28T14:16:48+00:00",
"order_id" : 583581,
"products" : [
{
"base_price" : 10.99,
"discount_percentage" : 0,
"quantity" : 1,
"manufacturer" : "Tigress Enterprises",
"tax_amount" : 0,
"product_id" : 19024,
"category" : "Women's Accessories",
"sku" : "ZO0082400824",
"taxless_price" : 10.99,
"unit_discount_amount" : 0,
"min_price" : 5.17,
"_id" : "sold_product_583581_19024",
"discount_amount" : 0,
"created_on" : "2016-12-25T14:16:48+00:00",
"product_name" : "Snood - white/grey/peach",
"price" : 10.99,
"taxful_price" : 10.99,
"base_unit_price" : 10.99
},
{
"base_price" : 32.99,
"discount_percentage" : 0,
"quantity" : 1,
"manufacturer" : "Tigress Enterprises",
"tax_amount" : 0,
"product_id" : 19260,
"category" : "Women's Clothing",
"sku" : "ZO0071900719",
"taxless_price" : 32.99,
"unit_discount_amount" : 0,
"min_price" : 17.15,
"_id" : "sold_product_583581_19260",
"discount_amount" : 0,
"created_on" : "2016-12-25T14:16:48+00:00",
"product_name" : "Cardigan - grey",
"price" : 32.99,
"taxful_price" : 32.99,
"base_unit_price" : 32.99
}
],
"sku" : [
"ZO0082400824",
"ZO0071900719"
],
"taxful_total_price" : 43.98,
"taxless_total_price" : 43.98,
"total_quantity" : 2,
"total_unique_products" : 2,
"type" : "order",
"user" : "rani",
"geoip" : {
"country_iso_code" : "EG",
"location" : {
"lon" : 31.3,
"lat" : 30.1
},
"region_name" : "Cairo Governorate",
"continent_name" : "Africa",
"city_name" : "Cairo"
},
"event" : {
"dataset" : "sample_ecommerce"
}
}
...
}
]
}
}
}
}
value_count
指标是单值指标聚合,用于计算聚合所基于的值的数量。
GET opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"number_of_values": {
"value_count": {
"field": "taxful_total_price"
}
}
}
}
...
"aggregations" : {
"number_of_values" : {
"value" : 4675
}
}
}
存储桶聚合将文档集分类为存储桶。存储桶聚合的类型决定了给定文档的存储桶。
date_histogram
聚合使用日期数学来生成时间序列数据的直方图。
网站每月获得的点击次数
GET opensearch_dashboards_sample_data_logs/_search
{
"size": 0,
"aggs": {
"logs_per_month": {
"date_histogram": {
"field": "@timestamp",
"interval": "month"
}
}
}
}
...
"aggregations" : {
"logs_per_month" : {
"buckets" : [
{
"key_as_string" : "2020-10-01T00:00:00.000Z",
"key" : 1601510400000,
"doc_count" : 1635
},
{
"key_as_string" : "2020-11-01T00:00:00.000Z",
"key" : 1604188800000,
"doc_count" : 6844
},
{
"key_as_string" : "2020-12-01T00:00:00.000Z",
"key" : 1606780800000,
"doc_count" : 5595
}
]
}
}
}
histogram
聚合根据指定的时间间隔存储文档。
通过 histogram
聚合,您可以非常轻松地可视化给定文档范围内的值的分布。当然,现在 OpenSearch 不会返回实际的图表,这就是 OpenSearch 仪表板的用途。但它会给你 JSON 响应,你可以用它来构建你自己的图表。
以下示例按 10,000 个间隔对 number_of_bytes
字段进行存储:
GET opensearch_dashboards_sample_data_logs/_search
{
"size": 0,
"aggs": {
"number_of_bytes": {
"histogram": {
"field": "bytes",
"interval": 10000
}
}
}
}
...
"aggregations" : {
"number_of_bytes" : {
"buckets" : [
{
"key" : 0.0,
"doc_count" : 13372
},
{
"key" : 10000.0,
"doc_count" : 702
}
]
}
}
}
range
聚合允许您定义每个存储桶的范围。
例如,您可以查找 1000 到 2000、2000 到 3000、3000 到 4000 之间的字节数。在 range
参数中,您可以将范围定义为数组对象。
GET opensearch_dashboards_sample_data_logs/_search
{
"size": 0,
"aggs": {
"number_of_bytes_distribution": {
"range": {
"field": "bytes",
"ranges": [
{
"from": 1000,
"to": 2000
},
{
"from": 2000,
"to": 3000
},
{
"from": 3000,
"to": 4000
}
]
}
}
}
}
...
"aggregations" : {
"number_of_bytes_distribution" : {
"buckets" : [
{
"key" : "1000.0-2000.0",
"from" : 1000.0,
"to" : 2000.0,
"doc_count" : 805
},
{
"key" : "2000.0-3000.0",
"from" : 2000.0,
"to" : 3000.0,
"doc_count" : 1369
},
{
"key" : "3000.0-4000.0",
"from" : 3000.0,
"to" : 4000.0,
"doc_count" : 1422
}
]
}
}
}
terms
聚合动态地为字段的每个唯一术语创建一个存储桶。
以下示例使用 terms
聚合来查找 Web 日志数据中每个响应代码的文档数:
GET opensearch_dashboards_sample_data_logs/_search
{
"size": 0,
"aggs": {
"response_codes": {
"terms": {
"field": "response.keyword",
"size": 10
}
}
}
}
...
"aggregations" : {
"response_codes" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "200",
"doc_count" : 12832
},
{
"key" : "404",
"doc_count" : 801
},
{
"key" : "503",
"doc_count" : 441
}
]
}
}
}