概要:对ES的metrics aggregation文档做了一点翻译工作,可能有不对的地方,大家可以查看原文
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics.html
这个类型的聚合操作根据选择的document 的 值 计算 指标。这个值可以从document 的 fields中提取,也可以通过脚本生成。
Numeric metrics aggregation 是一种特殊的metrics aggregation,它的输出为数值。
一些metrics aggregation输出一个数值度量(如avg),也称为单一数值指标聚合(single-value);
其他生成多个指标(如数据),也被称为多值数字指标聚合(multi-value)。
single-value和multi-value Numberic metrics aggregation起到不同的作用,特别是作为一些bucekt aggregation的 sub-aggregation 时。
(一些bucket aggregation 要求你基于每个桶,返回 指标值)
Avg aggregation
:1个返回值的 metrics aggregation,在选定的document 上,选择特定的数值field ,对这些字段计算平均值。
假设文档的数据为代表学生的考试成绩(0到100之间),我们可以平均成绩:
curl -X POST "localhost:9200/exams/_search?size=0&pretty" -H 'Content-Type: application/json' -d'
{
"aggs": {
"avg_grade": { "avg": { "field": "grade" } }
}
}
'
上面的聚合操作在所有文档上计算平均成绩。聚合类型为avg、字段为数值字段。以上返回结果如下:
{
...
"aggregations": {
"avg_grade": {
"value": 75.0
}
}
}
聚合的名字(avg_grade)可以在返回结果中获得。
Script:
假设考试是非常困难的,你需要对成绩进行修正。使用runtime field 获取修正后的平均值:
curl -X POST "localhost:9200/exams/_search?size=0&pretty" -H 'Content-Type: application/json' -d'
{
"runtime_mappings": {
"grade.corrected": {
"type": "double",
"script": {
"source": "emit(Math.min(100, doc[\u0027grade\u0027].value * params.correction))",
"params": {
"correction": 1.2
}
}
}
},
"aggs": {
"avg_corrected_grade": {
"avg": {
"field": "grade.corrected"
}
}
}
}
'
Missing value:
默认情况,对于文档中字段的空值,会省略;但是也可以对空值设计一个默认值
curl -X POST "localhost:9200/exams/_search?size=0&pretty" -H 'Content-Type: application/json' -d'
{
"aggs": {
"grade_avg": {
"avg": {
"field": "grade",
"missing": 10
}
}
}
}
'
document 没有字段 grade时,会设置默认值10;
Histogram fields:直方图字段
当对直方图字段进行平均值计算时,每个values 中的元素需要根据counts中的字段进行加权操作
PUT metrics_index/_doc/1{
"network.name" : "net-1",
"latency_histo" : {
"values" : [0.1, 0.2, 0.3, 0.4, 0.5],
"counts" : [3, 7, 23, 12, 6]
}}
PUT metrics_index/_doc/2{
"network.name" : "net-2",
"latency_histo" : {
"values" : [0.1, 0.2, 0.3, 0.4, 0.5],
"counts" : [8, 17, 8, 7, 6]
}}
POST /metrics_index/_search?size=0{
"aggs": {
"avg_latency":
{ "avg": { "field": "latency_histo" }
}
}}
对于每个直方图字段,平均聚合将values数组中的每个数字乘以counts数组中的相关数字;最终,它将计算所有直方图上这些值的平均值,并返回以下结果:
{
...
"aggregations": {
"avg_latency": {
"value": 0.29690721649
}
}}
Boxplot aggregation:
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-boxplot-aggregation.html
Cardinality aggregation:
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-cardinality-aggregation.html#search-aggregations-metrics-cardinality-aggregation
Extended stats aggregation
一个会返回多个值的metrics aggregation, 从要聚合的文档中提取数值,对数值进行统计,返回统计信息。
extended_stats aggregations 是 stats aggregation 的扩展版本 , 添加了额外的度量,如sum_of_squares, variance, std_deviation and std_deviation_bounds.
假设 数据由代表学生考试成绩(0到100)的document组成。
GET /exams/_search
{
"size": 0,
"aggs": {
"grades_stats": { "extended_stats": { "field": "grade" } }
}
}
以上的聚合操作计算所有文档中关于"grade"的统计信息。统计类型为"extended_stats",统计字段为文档中的数值字段,返回结果如下:
std_deviation和variance是作为总体度量来计算的,所以它们总是分别与std_deviation_population和variance_population相同。
{
...
"aggregations": {
"grades_stats": {
"count": 2, 计数
"min": 50.0, 最小值
"max": 100.0, 最大值
"avg": 75.0, 平均值
"sum": 150.0, 总和
"sum_of_squares": 12500.0, 平方和
"variance": 625.0,
"variance_population": 625.0, 总体方差
"variance_sampling": 1250.0, 样本方差
"std_deviation": 25.0, 标准差
"std_deviation_population": 25.0, 总体标准偏差的方差
"std_deviation_sampling": 35.35533905932738, 样本标准偏差
"std_deviation_bounds": { 标准差范围(上下界)
"upper": 125.0,
"lower": 25.0,
"upper_population": 125.0,
"lower_population": 25.0,
"upper_sampling": 145.71067811865476,
"lower_sampling": 4.289321881345245
}
}
}}
聚合操作的名称(grades_stats)也可以作为键,从返回的响应中检索聚合结果。
Standard Deviation Bounds[标准差范围(上下界)]
默认情况,extended_stats会返回一个叫做std_deviation_bounds的对象,它提供了一个距离均值正负两个标准差的区间。
这是可视化数据方差的一种有用方法。如果你想要一个不同的边界,例如三个标准偏差,你可以在请求中设置sigma:
GET /exams/_search{
"size": 0,
"aggs": {
"grades_stats": {
"extended_stats": {
"field": "grade",
"sigma": 3
}
}
}}
sigma控制了正/负的多少个标准差应该被显示
sigma可以被设置为任何非负值;这意味着你可以定义非整数值,比如1.5。值0是有效的,但将简单地返回上界和下界的平均值。
上界和下界是作为总体度量来计算的,因此它们总是分别与upper_population和lower_population相同。
script
如果需要对没有索引的值进行聚合,请使用runtime field。比如,我们发现我们一直在做的成绩是针对一个高于学生水平的考试,我们想“纠正”它:
GET /exams/_search{
"size": 0,
"runtime_mappings": {
"grade.corrected": {
"type": "double",
"script": {
"source": "emit(Math.min(100, doc['grade'].value * params.correction))",
"params": {
"correction": 1.2
}
}
}
},
"aggs": {
"grades_stats": {
"extended_stats": { "field": "grade.corrected" }
}
}}
Missing value
缺失参数 定义了如何处理缺失值的 document。默认情况下,它们将被忽略,但也可以将它们视为具有值。
GET /exams/_search
{
"size": 0,
"aggs": {
"grades_stats": {
"extended_stats": {
"field": "grade",
"missing": 0
}
}
}
}
Geo-bounds aggregation
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-geobounds-aggregation.html
Geo bound 是一种 Metric aggregation,用来计算包含所有地理值的边界。
示例:
PUT /museums
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
POST /museums/_bulk?refresh
{"index":{"_id":1}}
{"location": "52.374081,4.912350", "name": "NEMO Science Museum"}
{"index":{"_id":2}}
{"location": "52.369219,4.901618", "name": "Museum Het Rembrandthuis"}
{"index":{"_id":3}}
{"location": "52.371667,4.914722", "name": "Nederlands Scheepvaartmuseum"}
{"index":{"_id":4}}
{"location": "51.222900,4.405200", "name": "Letterenhuis"}
{"index":{"_id":5}}
{"location": "48.861111,2.336389", "name": "Musée du Louvre"}
{"index":{"_id":6}}
{"location": "48.860000,2.327000", "name": "Musée d'Orsay"}
POST /museums/_search?size=0
{
"query": {
"match": { "name": "musée" }
},
"aggs": {
"viewport": {
"geo_bounds": {
"field": "location", geo_bounds聚合 指定 用于获取边界的字段
"wrap_longitude": true wrap_longitude是一个可选参数,用于指定边界框是否允许与国际日期线重叠。默认值为true。
}
}
}
}
上面的聚合 演示了如何计算店铺类型的所有文档的位置字段的边界框
返回结果如下:
......
"aggregations": {
"viewport": {
"bounds": {
"top_left": {
"lat": 48.86111099738628,
"lon": 2.3269999679178
},
"bottom_right": {
"lat": 48.85999997612089,
"lon": 2.3363889567553997
}
}
}
}
......
Geo Bounds Aggregation on geo_shape fields
geo_bounds aggregation 支持 geo_shape 字段;
如果wrap_longitude设置为true(默认值),边界框可以与国际日期线重叠,并返回一个左上方(top_left)经度大于右上方(top_right)经度的边界。
例如,地理边界框的右上方经度通常会大于左下方的经度。然而,当该区域穿过180°子午线时,左下方的经度值将大于右上方的经度值。有关更多信息,请参阅开放地理空间联盟网站上的地理边界框
PUT /places
{
"mappings": {
"properties": {
"geometry": {
"type": "geo_shape"
}
}
}
}
POST /places/_bulk?refresh
{"index":{"_id":1}}
{"name": "NEMO Science Museum", "geometry": "POINT(4.912350 52.374081)" }
{"index":{"_id":2}}
{"name": "Sportpark De Weeren", "geometry": { "type": "Polygon", "coordinates": [ [ [ 4.965305328369141, 52.39347642069457 ], [ 4.966979026794433, 52.391721758934835 ], [ 4.969425201416015, 52.39238958618537 ], [ 4.967944622039794, 52.39420969150824 ], [ 4.965305328369141, 52.39347642069457 ] ] ] } }
POST /places/_search?size=0
{
"aggs": {
"viewport": {
"geo_bounds": {
"field": "geometry"
}
}
}
}
返回结果:
...
"aggregations": {
"viewport": {
"bounds": {
"top_left": {
"lat": 52.39420966710895,
"lon": 4.912349972873926
},
"bottom_right": {
"lat": 52.374080987647176,
"lon": 4.969425117596984
}
}
}
}
...
Geo-centroid aggregation
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-geocentroid-aggregation.html
一种度量集合,从地理的所有座标值计算加权质心
例如:
PUT /museums
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
POST /museums/_bulk?refresh
{"index":{"_id":1}}
{"location": "52.374081,4.912350", "city": "Amsterdam", "name": "NEMO Science Museum"}
{"index":{"_id":2}}
{"location": "52.369219,4.901618", "city": "Amsterdam", "name": "Museum Het Rembrandthuis"}
{"index":{"_id":3}}
{"location": "52.371667,4.914722", "city": "Amsterdam", "name": "Nederlands Scheepvaartmuseum"}
{"index":{"_id":4}}
{"location": "51.222900,4.405200", "city": "Antwerp", "name": "Letterenhuis"}
{"index":{"_id":5}}
{"location": "48.861111,2.336389", "city": "Paris", "name": "Musée du Louvre"}
{"index":{"_id":6}}
{"location": "48.860000,2.327000", "city": "Paris", "name": "Musée d'Orsay"}
POST /museums/_search?size=0
{
"aggs": {
"centroid": {
"geo_centroid": {
"field": "location"
}
}
}
}
geo_centroid聚合指定用于计算质心的字段。(注:字段必须是Geo-point类型)
上例演示了 如何计算location字段的质心,返回结果如下:
......
"aggregations": {
"centroid": {
"location": {
"lat": 51.00982965203002,
"lon": 3.9662131341174245
},
"count": 6
}
}
......
当将geo_centroid聚合作为其他桶聚合的子聚合时,它会更有趣。
POST /museums/_search?size=0
{
"aggs": {
"cities": {
"terms": { "field": "city.keyword" },
"aggs": {
"centroid": {
"geo_centroid": { "field": "location" }
}
}
}
}
}
结果如下:根据城市分组、对每组城市做geo_centroid聚合操作
{
........
"aggregations": {
"cities": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Amsterdam",
"doc_count": 3,
"centroid": {
"location": {
"lat": 52.371655656024817,
"lon": 4.909563297405839
},
"count": 3
}
},
{
"key": "Paris",
"doc_count": 2,
"centroid": {
"location": {
"lat": 48.86055548675358,
"lon": 2.3316944623366
},
"count": 2
}
},
{
"key": "Antwerp",
"doc_count": 1,
"centroid": {
"location": {
"lat": 51.22289997059852,
"lon": 4.40519998781383
},
"count": 1
}
}
]
}
}
}
对于geo_shape类型字段的地理质心
地理的质心度量比点的质心度量更微妙。包含形状的特定聚合桶的质心是桶中最高维形状类型的质心。例如,如果一个桶包含由多边形和直线组成的形状,那么这些直线就不构成质心度量。每一种形状的质心都是不同的。通过圆摄取的信封和圆被视为多边形。
集合类型 | 质心计算 |
---|---|
点集合 | 所有坐标的加权平均值线段 集合 |
线段 集合 | 每个线段的所有质心的加权平均值,其中每个线段的权重是其长度的度数 |
多边形 集合 | 一个多边形中由每两个连续顶点和起始点组成的所有三角形的所有三角形的重心的加权平均值。洞的重量为负。权重表示以deg^2计算的三角形的面积 |
几何体集合 | 所有具有最高维度的基础几何图形的质心。如果多边形和线和/或点,那么线和/或点将被忽略。如果线和点,那么点被忽略 |
PUT /places
{
"mappings": {
"properties": {
"geometry": {
"type": "geo_shape"
}
}
}
}
POST /places/_bulk?refresh
{"index":{"_id":1}}
{"name": "NEMO Science Museum", "geometry": "POINT(4.912350 52.374081)" }
{"index":{"_id":2}}
{"name": "Sportpark De Weeren", "geometry": { "type": "Polygon", "coordinates": [ [ [ 4.965305328369141, 52.39347642069457 ], [ 4.966979026794433, 52.391721758934835 ], [ 4.969425201416015, 52.39238958618537 ], [ 4.967944622039794, 52.39420969150824 ], [ 4.965305328369141, 52.39347642069457 ] ] ] } }
POST /places/_search?size=0
{
"aggs": {
"centroid": {
"geo_centroid": {
"field": "geometry"
}
}
}
}
返回结果:【这个好像是付费操作】
{
...
"aggregations": {
"centroid": {
"location": {
"lat": 52.39296147599816,
"lon": 4.967404240742326
},
"count": 2
}
}
}
使用geo_centroid作为geohash_grid的子聚合
geohash_grid聚合将文档(而不是单个地理点)放入桶中。如果文档的geo_point字段包含多个值,则可以将文档分配给多个bucket,即使一个或多个地理点位于bucket边界之外。
如果还使用了质心子聚合,则使用桶中的所有地理点(包括桶边界外的地理点)计算每个质心。这可能导致在桶边界之外的质心。
Geo-Line
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-geo-line.html
Matrix stats
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-matrix-stats-aggregation.html
Matrix stats聚合操作结果为数字,计算一组数据的以下统计信息
count:返回field的数量
mean:The average value for each field.
variance:方差
skewness:Per field measurement quantifying the asymmetric distribution around the mean.
kurtosis:Per field measurement quantifying the shape of the distribution.
covariance:
Max
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-max-aggregation.html
返回最大值
请求:
curl -X POST "localhost:9200/sales/_search?size=0&pretty" -H 'Content-Type: application/json' -d'
{
"aggs": {
"max_price": { "max": { "field": "price" } }
}
}
'
返回:
{
...
"aggregations": {
"max_price": {
"value": 200.0
}
}}
script:
通过脚本产生的新字段,也可以进行max聚合操作
POST /sales/_search{
"size": 0,
"runtime_mappings": {
"price.adjusted": {
"type": "double",
"script": """
double price = doc['price'].value;
if (doc['promoted'].value) {
price *= 0.8;
}
emit(price);
"""
}
},
"aggs": {
"max_price": {
"max": { "field": "price.adjusted" }
}
}}
......
Missing value:
关于缺失的值,默认的情况下会被忽略,但是也可以指定默认值。
POST /sales/_search{
"aggs" : {
"grade_max" : {
"max" : {
"field" : "grade",
"missing": 10
}
}
}}
Histogram fields:直方图字段
…
Median absolute deviation
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-median-absolute-deviation-aggregation.html
Min
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-min-aggregation.html
返回最小值
POST /sales/_search?size=0{
请求报文:
"aggs": {
"min_price": { "min": { "field": "price" } }
}}
返回报文:
{
...
"aggregations": {
"min_price": {
"value": 10.0
}
}}
script:
对通过脚本产生的字段,求最小值
POST /sales/_search
{
"size": 0,
"runtime_mappings": {
"price.adjusted": {
"type": "double",
"script": """
double price = doc['price'].value;
if (doc['promoted'].value) {
price *= 0.8;
}
emit(price);
"""
}
},
"aggs": {
"min_price": {
"min": { "field": "price.adjusted" }
}
}}
Missing value:
对于缺失的值,默认忽略,但是也可以设置默认值
POST /sales/_search{
"aggs": {
"grade_min": {
"min": {
"field": "grade",
"missing": 10
}
}
}}
Histogram fields:
Percentile ranks
返回指定数据在数据集中的位置百分比
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-percentile-rank-aggregation.html
返回多个值,计算从聚合文档中提取的数值的一个或多个百分位排名。这些值可以从文档中的特定数字或直方图字段中提取。
结果反应观察值低于某一数值的百分比。例如,如果一个值大于或等于观察值的95%,则称其处于第95百分位。
假设你的数据由网站加载时间组成。您可能有一个服务协议,95%的页面加载在500ms内完成,99%的页面加载在600ms内完成。
GET latency/_search{
"size": 0,
"aggs": {
"load_time_ranks": {
"percentile_ranks": {
"field": "load_time",
"values": [ 500, 600 ]
}
}
}}
字段load_time的类型必须为数字
返回结果:
{
...
"aggregations": {
"load_time_ranks": {
"values": {
"500.0": 90.01,
"600.0": 100.0
}
}
}}
以上结果表明,90.01%的访问在500ms内完成;100%的访问在600ms内完成。
keyed:默认值为true,表示以数组的形式返回结果;设置false会以对象的形式返回结果
GET latency/_search{
"size": 0,
"aggs": {
"load_time_ranks": {
"percentile_ranks": {
"field": "load_time",
"values": [ 500, 600 ],
"keyed": false
}
}
}}
返回:
{
...
"aggregations": {
"load_time_ranks": {
"values": [
{
"key": 500.0,
"value": 90.01
},
{
"key": 600.0,
"value": 100.0
}
]
}
}}
Script:对运行时字段使用这个聚合操作
GET latency/_search{
"size": 0,
"runtime_mappings": {
"load_time.seconds": {
"type": "long",
"script": {
"source": "emit(doc['load_time'].value / params.timeUnit)",
"params": {
"timeUnit": 1000
}
}
}
},
"aggs": {
"load_time_ranks": {
"percentile_ranks": {
"values": [ 500, 600 ],
"field": "load_time.seconds"
}
}
}}
HDR Histogram:
Missing value:
对于缺失值,默认忽略,也可以指定默认值
GET latency/_search{
"size": 0,
"aggs": {
"load_time_ranks": {
"percentile_ranks": {
"field": "load_time",
"values": [ 500, 600 ],
"missing": 10
}
}
}}
Percentiles
返回数据集中指定百分比上的数字
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-percentile-aggregation.html
多值度量聚合,计算从 聚合文档 中提取的数值的一个或多个百分位数。这些值可以从文档中的特定数字或直方图字段中提取。
百分数表示观察值的某个百分比出现的点。例如,第95个百分位数是大于95%的观测值。
百分比通常被用来寻找异常值。在正态分布中,0.13%和99.87%代表三个标准差的平均值。任何低于三个标准偏差的数据通常被认为是异常。
当检索到一个百分比范围时,可以使用它们来估计数据分布,并确定数据是否倾斜、双峰等。
举例:
假设你的数据由网站加载时间组成。平均加载时间和中值加载时间对管理员并不是特别有用。因为,它很容易被一个缓慢的响应扭曲。
GET latency/_search{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time"
}
}
}}
**字段load_time的类型必须为数字**
默认情况下percentile聚合返回1个范围内的百分比值[ 1, 5, 25, 50, 75, 95, 99 ]
{
...
"aggregations": {
"load_time_outlier": {
"values": {
"1.0": 5.0, //1%的访问在5ms内响应
"5.0": 25.0, //5%的访问在25ms内响应
"25.0": 165.0,
"50.0": 445.0,
"75.0": 725.0,
"95.0": 945.0,
"99.0": 985.0 //99%的访问在985ms内响应
}
}
}}
如上,聚合将返回默认范围内每个百分比的计算值。如果我们假设响应时间以毫秒为单位,很明显,网页通常在10-725ms内加载,但偶尔会达到945-985ms。
通常,管理员只对异常值——极端的百分位数感兴趣。我们可以只指定我们感兴趣的百分比(请求的百分比必须是0-100(含0-100)之间的值):
GET latency/_search{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"percents": [ 95, 99, 99.9 ]
}
}
}}
keyed:默认值为true,表示以数组的形式返回结果;设置false会以对象的形式返回结果
GET latency/_search{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"keyed": false
}
}
}}
返回:
{
...
"aggregations": {
"load_time_outlier": {
"values": [
{
"key": 1.0,
"value": 5.0
},
{
"key": 5.0,
"value": 25.0
},
{
"key": 25.0,
"value": 165.0
},
{
"key": 50.0,
"value": 445.0
},
{
"key": 75.0,
"value": 725.0
},
{
"key": 95.0,
"value": 945.0
},
{
"key": 99.0,
"value": 985.0
}
]
}
}}
Script:对运行时字段使用这个聚合操作
GET latency/_search{
"size": 0,
"runtime_mappings": {
"load_time.seconds": {
"type": "long",
"script": {
"source": "emit(doc['load_time'].value / params.timeUnit)",
"params": {
"timeUnit": 1000
}
}
}
},
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time.seconds"
}
}
}}
Percentiles are (usually) approximate:百分比通常是近似结果
有许多不同的算法来计算百分位数。朴素的实现只是将所有值存储在一个已排序的数组中。要找到第50个百分位数,只需找到位于my_array[count(my_array) * 0.5]处的值。
显然,这种简单的实现是不按比例伸缩的——已排序的数组随数据集中值的数量线性增长。为了计算Elasticsearch集群中数十亿值的百分位数,需要计算近似的百分位数。
百分位度量所使用的算法称为TDigest(由Ted Dunning在使用T-Digests计算精确分位数中引入)。
https://github.com/tdunning/t-digest/blob/master/docs/t-digest-paper/histo.pdf
Compression:压缩
近似算法必须平衡内存利用率和估计精度。这种平衡可以使用压缩参数来控制:
GET latency/_search{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"tdigest": {
"compression": 200
}
}
}
}}
压缩控制内存使用和近似错误
这个压缩值越大,占用内存和精度就越大;默认情况下,压缩值为100;
HDR Histogram:
Rate
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-rate-aggregation.html
rate度量聚合只能在日期柱状图中使用,并计算每个日期柱状图bucket中的文档或字段的速率。可以从文档中的特定数字或直方图字段中提取字段值来生成字段值。
Scripted metric
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-scripted-metric-aggregation.html
使用脚本执行的度量聚合,以提供度量输出。
使用脚本会导致较慢的搜索速度,参考:https://www.elastic.co/guide/en/elasticsearch/reference/7.13/scripts-and-search-speed.html
POST ledger/_search?size=0
使用脚本聚合计算 销售 和 成本 的总利润
{
"query": {
"match_all": {}
},
"aggs": {
"profit": {
"scripted_metric": {
"init_script": "state.transactions = []",
"map_script": "state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
"combine_script": "double profit = 0; for (t in state.transactions) { profit += t } return profit",
"reduce_script": "double profit = 0; for (a in states) { profit += a } return profit"
}
}
}}
返回结果:
{
"took": 218,
...
"aggregations": {
"profit": {
"value": 240.0
}
}}
…
Stats
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-stats-aggregation.html
多值度量聚合,计算从聚合文档中提取的数值的统计信息。这个聚合操作里返回包括以下聚合结果:min、max、sum、count、avg
ps:没有单独的count聚合操作
假设数据由代表学生考试成绩(0到100)的文档组成
POST /exams/_search?size=0{
"aggs": {
"grades_stats": { "stats": { "field": "grade" } }
}}
返回结果:
{
...
"aggregations": {
"grades_stats": {
"count": 2,
"min": 50.0,
"max": 100.0,
"avg": 75.0,
"sum": 150.0
}
}}
Script:对运行时字段执行聚合操作
POST /exams/_search{
"size": 0,
"runtime_mappings": {
"grade.weighted": {
"type": "double",
"script": """
emit(doc['grade'].value * doc['weight'].value)
"""
}
},
"aggs": {
"grades_stats": {
"stats": {
"field": "grade.weighted"
}
}
}}
Missing value:默认情况,缺失值忽略,也可以指定默认值
POST /exams/_search?size=0{
"aggs": {
"grades_stats": {
"stats": {
"field": "grade",
"missing": 0
}
}
}}
String stats
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-string-stats-aggregation.html
多值度量聚合,计算从聚合文档中提取的字符串值的统计信息。这些值可以从特定的关键字字段中检索。
count – 计数的非空字段的数量。
min_length – 最短期限的长度。
max_length – 最长长度。
avg_length – 计算所有项的平均长度。
entropy – Shannon熵值计算的所有项收集的聚合。香农熵量化了场中包含的信息量。它是一个非常有用的度量标准,用于测量数据集的广泛属性,如多样性、相似性、随机性等。
POST /my-index-000001/_search?size=0{
"aggs": {
"message_stats": { "string_stats": { "field": "message.keyword" } }
}}
上述聚合操作计算所有文档中的消息字段的字符串统计信息。聚合类型是string_stats,字段参数定义将计算统计值的文档的字段。以上内容将返回以下内容:
{
...
"aggregations": {
"message_stats": {
"count": 5,
"min_length": 24,
"max_length": 30,
"avg_length": 28.8,
"entropy": 3.94617750050791
}
}}
Character distribution:字符分布
Shannon熵值的计算是基于聚合所收集的每个字符在所有术语中出现的概率。要查看所有字符的概率分布,可以添加show_distribution(默认值:false)参数。
POST /my-index-000001/_search?size=0
{ "aggs": { "message_stats": { "string_stats": { "field": "message.keyword", "show_distribution": true } } }}将show_distribution参数设置为true,以便在结果中返回所有字符的概率分布。{ ... "aggregations": { "message_stats": { "count": 5, "min_length": 24, "max_length": 30, "avg_length": 28.8, "entropy": 3.94617750050791, "distribution": { " ": 0.1527777777777778, "e": 0.14583333333333334, "s": 0.09722222222222222, "m": 0.08333333333333333, "t": 0.0763888888888889, "h": 0.0625, "a": 0.041666666666666664, "i": 0.041666666666666664, "r": 0.041666666666666664, "g": 0.034722222222222224, "n": 0.034722222222222224, "o": 0.034722222222222224, "u": 0.034722222222222224, "b": 0.027777777777777776, "w": 0.027777777777777776, "c": 0.013888888888888888, "E": 0.006944444444444444, "l": 0.006944444444444444, "1": 0.006944444444444444, "2": 0.006944444444444444, "3": 0.006944444444444444, "4": 0.006944444444444444, "y": 0.006944444444444444 } } }}分布对象表示每个字符在所有项中出现的概率。字符按降序概率排序。
Script:对运行时字段使用这个聚合操作
POST /my-index-000001/_search{
"size": 0,
"runtime_mappings": {
"message_and_context": {
"type": "keyword",
"script": """
emit(doc['message.keyword'].value + ' ' + doc['context.keyword'].value)
"""
}
},
"aggs": {
"message_stats": {
"string_stats": { "field": "message_and_context" }
}
}}
Missing value:默认情况下,对于缺省值会忽略,可以对缺省值设置默认值
POST /my-index-000001/_search?size=0{
"aggs": {
"message_stats": {
"string_stats": {
"field": "message.keyword",
"missing": "[empty message]"
}
}
}}
Sum
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-sum-aggregation.html
求和操作,对从聚合文档中提取的数值进行求和的单值度量聚合。这些值可以从特定的数字或直方图字段中提取。
POST /sales/_search?size=0{
"query": {
"constant_score": {
"filter": {
"match": { "type": "hat" }
}
}
},
"aggs": {
"hat_prices": { "sum": { "field": "price" } }
}}
返回报文:
{
...
"aggregations": {
"hat_prices": {
"value": 450.0
}
}}
Script:对运行时字段执行这个聚合操作
POST /sales/_search?size=0{
"runtime_mappings": {
"price.weighted": {
"type": "double",
"script": """
double price = doc['price'].value;
if (doc['promoted'].value) {
price *= 0.8;
}
emit(price);
"""
}
},
"query": {
"constant_score": {
"filter": {
"match": { "type": "hat" }
}
}
},
"aggs": {
"hat_prices": {
"sum": {
"field": "price.weighted"
}
}
}}
Missing value:默认情况下,缺省值将被忽略,可以给缺省值设置默认值
POST /sales/_search?size=0{
"query": {
"constant_score": {
"filter": {
"match": { "type": "hat" }
}
}
},
"aggs": {
"hat_prices": {
"sum": {
"field": "price",
"missing": 100
}
}
}}
Histogram fields:
T-test
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-ttest-aggregation.html
一个t_test度量聚合,执行一个统计假设检验,其中检验统计量遵循一个Student的t分布,在null假设下对从聚合文档中提取的数值进行检验。在实践中,这将告诉你两个总体均值之间的差异是否具有统计学意义,是否仅仅是偶然发生的。
Top hits
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-top-hits-aggregation.html
top_hits度量聚合器 跟踪被聚合的最相关文档。此聚合器作用于子聚合器,以便可以将最匹配的文档聚合到每个桶中。
top_hits聚合器可以通过bucket聚合器有效地根据某些字段对结果集进行分组。一个或多个桶聚合器决定将结果集分成哪些属性。
选项
- from - 从你想要获取的第一个结果的偏移量。
- size - 每个桶返回的最大顶部匹配命中数。默认情况下,返回前三个匹配的命中。
- sort -顶部匹配的命中应该如何排序。默认情况下,按主查询的得分排序。
Supported per hit features:支持的特性
Explain
Named queries
Search fields
Source filtering
Stored fields
Script fields
Doc value fields
Include versions
Include Sequence Numbers and Primary Terms
Top_hits不支持rescore参数。对聚合结果不进行评分,只对搜索结果进行评分。要更改聚合所使用的分数,请使用function_score或script_score查询。
示例:按类型对销售进行分组,每个类型显示最后的销售。对于每个销售,源中只包含日期和价格字段。
POST /sales/_search?size=0{
"aggs": {
"top_tags": {
"terms": {
"field": "type",
"size": 3
},
"aggs": {
"top_sales_hits": {
"top_hits": {
"sort": [
{
"date": {
"order": "desc"
}
}
],
"_source": {
"includes": [ "date", "price" ]
},
"size": 1
}
}
}
}
}}
返回结果:
{
...
"aggregations": {
"top_tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "hat",
"doc_count": 3,
"top_sales_hits": {
"hits": {
"total" : {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "_doc",
"_id": "AVnNBmauCQpcRyxw6ChK",
"_source": {
"date": "2015/03/01 00:00:00",
"price": 200
},
"sort": [
1425168000000
],
"_score": null
}
]
}
}
},
{
"key": "t-shirt",
"doc_count": 3,
"top_sales_hits": {
"hits": {
"total" : {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "_doc",
"_id": "AVnNBmauCQpcRyxw6ChL",
"_source": {
"date": "2015/03/01 00:00:00",
"price": 175
},
"sort": [
1425168000000
],
"_score": null
}
]
}
}
},
{
"key": "bag",
"doc_count": 1,
"top_sales_hits": {
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "_doc",
"_id": "AVnNBmatCQpcRyxw6ChH",
"_source": {
"date": "2015/01/01 00:00:00",
"price": 150
},
"sort": [
1420070400000
],
"_score": null
}
]
}
}
}
]
}
}}
Field collapse example:字段折叠的例子
字段折叠或结果分组是一种功能,它将结果集逻辑地分组,每个组返回顶级文档。组的顺序由组中第一个文档的相关性决定。在Elasticsearch中,这可以通过桶聚合器实现,桶聚合器将top_hits聚合器包装为子聚合器。
在下面的例子中,我们在爬行的网页上进行搜索。对于每个网页,我们存储的主体和该网页所属的域。通过在域名 域 中定义terms聚合器,我们将网页的结果集按域名分组。然后将top_hits聚合器定义为子聚合器,以便在每个桶中收集最匹配的命中数。
还定义了一个max聚合器,terms聚合器的顺序特性使用它来根据桶中最相关文档的关联顺序返回桶。
POST /sales/_search
{
"query": {
"match": {
"body": "elections"
}
},
"aggs": {
"top_sites": {
"terms": {
"field": "domain",
"order": {
"top_hit": "desc"
}
},
"aggs": {
"top_tags_hits": {
"top_hits": {}
},
"top_hit": {
"max": {
"script": {
"source": "_score"
}
}
}
}
}
}
}
目前,需要min/max聚合器,以确保桶从terms聚合器是根据最相关的网页每个域的分数排序。不幸的是,top_hits聚合器还不能在术语聚合器的顺序选项中使用。
top_hits support in a nested or reverse_nested aggregator:在嵌套或反向嵌套聚合器中支持Top_hits
。。。。。。
Top metrics
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-top-metrics.html
top_metrics聚合从文档中选择具有最大或最小“排序”值的指标。
例如,获取文档中值最大的s的m字段的值:
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"}
}
}
}}
根据字段s降序排序,返回字段m的值
返回:
{
"aggregations": {
"tm": {
"top": [ {"sort": [3], "metrics": {"m": 2.718280076980591 } } ]
}
}}
在精神上,Top_metrics与top_hits非常相似,但因为它受到更多的限制,所以能够使用更少的内存完成工作,而且通常速度更快。
sort:
在聚合请求中的 sort 字段的功能 与 搜索请求中的 sort 字段完全相同,除了:
- 它不能用于二进制、平面、ip、关键字或文本字段。
- 它只支持一个排序值,因此不指定哪个文档获胜。
metrics:
- meterics确定 要返回顶部文档 中的字段。
- 单个字段:“metrics”: {“field”: “m”}
- 多个字段:“metrics”: [{“field”: “m”}, {“field”: “i”}
metrics.field支持的的字段的类型有:boolean,ip,keywords,numbers
除了keywords外,还支持相应类型的运行时字段。metrics.field不支持带有数组值的字段。对数组值进行top_metric聚合可能会返回不一致的结果。
下面的示例在几个字段类型上运行top_metrics聚合:
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.0, "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参数返回前几个文档的度量值:
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.0 } },
{"sort": [1], "metrics": {"m": 3.1414999961853027 } }
]
}
}
}
size的默认大小为1。最大默认大小是10,因为聚合的工作存储是“密集的”,这意味着我们为每个桶分配大小槽。10是一个非常保守的默认最大值,如果需要,可以通过修改top_metrics_max_size索引设置来提高它。但是要知道,大的数据可能会占用相当多的内存,特别是如果它们是在一个聚合中,这就像一个大的terms聚合。如果你还想养它,可以用以下方法:
PUT /test/_settings{
"top_metrics_max_size": 100}
如果 size 大于1,则 top_metrics聚合 不能作为排序的目标。
Examples:
Use with terms:和分组一起使用
这种聚合在term聚合中非常有用,例如,可以查找每个服务器报告的最后一个值。
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": {
"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": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 3 } } ]
}
}
],
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0
}
}
}
不像top_hits,可以根据top_metrics的结果对桶进行排序:
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": {
"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 } } ]
}
}
],
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0
}
}
}
Mixed sort types:混合的排序类型
根据 跨不同索引具有不同类型的字段 对top_metrics排序 会产生一些令人惊讶的结果:浮点字段总是独立于整数字段进行排序。
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.0], "metrics": {"m": 3.1414999961853027 } } ]
}
}}
Value count
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-metrics-valuecount-aggregation.html
单值度量聚合,计算从聚合文档中提取的值的数量。这些值可以从文档中的特定字段提取,也可以由提供的脚本生成。通常,此聚合器将与其他单值聚合一起使用。例如,当计算平均值时,人们可能会对计算平均值的值的数量感兴趣。
value_count 聚合操作不会对数据进行去重操作
POST /sales/_search?size=0
{
"aggs" : {
"types_count" : { "value_count" : { "field" : "type" } }
}
}
返回报文:
{
...
"aggregations": {
"types_count": {
"value": 7
}
}}
Script:对运行时字段使用这个聚合操作
POST /sales/_search
{
"size": 0,
"runtime_mappings": {
"tags": {
"type": "keyword",
"script": """
emit(doc['type'].value);
if (doc['promoted'].value) {
emit('hot');
}
"""
}
},
"aggs": {
"tags_count": {
"value_count": {
"field": "tags"
}
}
}}
Histogram fields:
Weighted avg
单值度量聚合,计算从聚合文档中提取的数值的加权平均值。这些值可以从文档中的特定数字字段中提取。
当计算常规平均值时,每个数据点都有相同的“权重”……它对最终值的贡献是相同的。另一方面,加权平均是对每个数据点进行不同的加权。从文档中提取每个数据点对最终值的贡献。
作为一个公式,加权平均值是∑(value * weight) / ∑(weight)
avg聚合操作可以被认为是一个weighted_avg,其中每个值的隐含权重为1。
weighted_avg的参数:
- value:计算的字段或者运行时字段:必须有
- weight:value 中定义的字段的权重:必须有
- format:返回结果的格式化字段;可选
value的参数配置:
- field:计算的字段或者扩展字段;必须有
- missing:默认值;可选
weight的参数配置:
- field:权重字段;必须有
- missing:默认值;可选
如果我们的文档有一个包含0-100个数字分数的“grade”字段和一个包含任意数字权重的“weight”字段,我们可以使用以下方法计算加权平均值:
POST /exams/_search
{
"size": 0,
"aggs": {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade"
},
"weight": {
"field": "weight"
}
}
}
}
}
返回报文:
{
...
"aggregations": {
"weighted_grade": {
"value": 70.0
}
}
}
虽然每个字段允许多个值,但只允许一个权重。如果聚合遇到一个具有多个权重的文档(例如,权重字段是一个多值字段),它将终止搜索。如果遇到这种情况,应该构建一个Runtime字段,将这些值组合成单个权重。
这个权重将独立应用于从值字段中提取的每个值。
这个例子展示了一个具有多个值的文档如何用单个权重计算平均值:
POST /exams/_doc?refresh
{
"grade": [1, 2, 3],
"weight": 2
}
POST /exams/_search
{
"size": 0,
"aggs": {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade"
},
"weight": {
"field": "weight"
}
}
}
}
}
返回报文:
{
...
"aggregations": {
"weighted_grade": {
"value": 2.0
}
}
}
这[1、2、3]将作为独立值计算,权重均为2
Runtime field:对运行时字段使用这个聚合操作
POST /exams/_doc?refresh
{
"grade": 100,
"weight": [2, 3]
}
POST /exams/_doc?refresh
{
"grade": 80,
"weight": 3
}
POST /exams/_search?filter_path=aggregations
{
"size": 0,
"runtime_mappings": {
"weight.combined": {
"type": "double",
"script": """
double s = 0;
for (double w : doc['weight']) {
s += w;
}
emit(s);
"""
}
},
"aggs": {
"weighted_grade": {
"weighted_avg": {
"value": {
"script": "doc.grade.value + 1"
},
"weight": {
"field": "weight.combined"
}
}
}
}
}
返回报文:
{
"aggregations": {
"weighted_grade": {
"value": 93.5
}
}
}
Missing value:
缺失的参数定义了如何处理缺失值的文档。值和权重的默认行为是不同的:
默认情况下,如果value字段缺失,则忽略文档,并将聚合转移到下一个文档。如果权重字段缺失,则假定它的权重为1(类似于正常平均值)。
这两个默认值都可以用缺少的参数覆盖:
POST /exams/_search
{
"size": 0,
"aggs": {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade",
"missing": 2
},
"weight": {
"field": "weight",
"missing": 3
}
}
}
}
}