《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.21.Aggregations(3) https://developer.aliyun.com/article/1229243
4、和聚合 sum
和聚合属于单值度量聚合,可从聚合文档中的数值字段或者直方图字段中计算出总和。
1)基础用法
获取订单中产品的总销量,并定义总销量字段为 count_sum ,该字段也将作为结果返回:
POST /order/_search?size=0 { "aggs" : { "count_sum" : { "sum" : { "field" : "count" } } } }
返回结果:
{ ... "aggregations" : { "count_sum" : { "value" : 179 } } }
2)缺失值
默认情况下,当文档中缺失计算字段值时,该文档将会被忽略,若我们希望使用这部分文档,可以通过设置 missing 参数。以下例子中,缺失字段的 price 将按照 1 来计算,所以结果为 180。
POST /order/_search?size=0 { "aggs" : { "count_sum" : { "sum" : { "field" : "count", "missing": 1 } } } }
3)Histogram fields
在直方图字段上计算和聚合,计算的方法为将文档数组中的 value 乘以对应位置的 count 后进行加和汇总。
以存储不同网络的预聚合直方图和延迟度量的索引为例(数据参见 平均值聚合avg 第3点):
POST /metrics_index/_search?size=0 { "aggs" : { "total_latency" : { "sum" : { "field" : "latency_histo" } } } }
计算 latency_histo 字段和聚合的方法为,将每个文档的 value 乘以对应位置的 count 后再计算总和,因此上述结果为:
{ ... "aggregations": { "sum_latency": { "value": 28.8 } } }
4)脚本
GET order/_search?size=0 { "runtime_mappings": { "price.weighted": { "type": "double", "script": """ double price = doc['price'].value; if (doc['price'].value > 20000) { price *= 0.8; } emit(price); """ } }, "aggs": { "sum_price": { "sum": { "field": "price.weighted" } } } }
5、去重聚合 cardinality
去重聚合属于单值度量聚合,用于计算文档中不同值的数量,这个结果会是一个接近真实的值。
1)基础用法
获取订单数据中的销售产品的品牌数量,定义销售产品品牌数量的名字为 brand_count ,该字段也将作为结果返回:
POST /order/_search?size=0 { "aggs" : { "brand_count" : { "cardinality" : { "field" : "brand" } } } }
返回结果:
{ ... "aggregations" : { "btand_count" : { "value" : 2 } } }
2)缺失值
默认情况下,当文档中缺失计算字段值时,该文档将会被忽略,若我们希望使用这部分文档,可以通过设置 missing 参数。以下例子中,缺失字段的 brand 将按照 "N/a" 来计算。
增加一条品牌为空的数据:
post _bulk {"index":{"_index":"order","_id":8}} {"sales_name":"Amy","product_name":"mate11","price":"5387.23","count":28,"order_time":"2021-06-11"}
计算聚合:
POST /order/_search?size=0 { "aggs" : { "brand_count" : { "cardinality" : { "field" : "brand", "missing": "N/a" } } } }
输出结果:
{ ... "aggregations" : { "brand_count" : { "value" : 3 } } }
3)精度控制
可以使用 precision_threshold 参数定义阈值进行精度控制,使用方法如下:
POST /order/_search?size=0 { "aggs" : { "brand_count" : { "cardinality" : { "field" : "brand", "precision_threshold" : 100 } } } }
以上述品牌数量为例,该参数定义的阈值意义是:当品牌的去重数量在 100 以内,那么去重返回的结果精度可以接近100%。也就是当聚合文档中去重字段数量小于 precision_threshold 定义的阈值时,预期返回的结果将接近准确值,如果高于这个阈值,那么预期返回的结果将变的不再准确。precision_threshold 支持的最大值是40000,高于这个数的阈值将具有与阈值40000相同的效果,默认值为3000。
去重聚合的计算基于 HyperLogLog++ (HLL)算法,获取字段的哈希值,通过哈希值的相似度来计算数量。当聚合文档过大,或者计算的去重字段值太大都会需要消耗更多的内存。对于 precision_threshold 阈值为 n 的精度控制,在执行时将消耗 n*8 bytes 的内存。因此当阈值越大,占用的内存也会越大。但当阈值低至100时,即使计算的数据集有百万条,误差仍然很低。
哈希运算在数字字段上执行的非常快,存储原始数值与存储哈希所需的内存基本相同或者更少。因此我们可对字符串类型的字段进行预计算,从而提高运算速度。在 ES 中可以使用 mapper-murmur3 的插件提前将字段值的哈希值存储在索引中,这样在运行聚合时会更快。这种预计算哈希值的场景,应用在非常大的数据集或者非常大的字段上效果比较明显,可以节省 CPU 和内存。当然在较小的字符串字段,也可以应用进行性能优化。
4)脚本
需要将多个字段组合进行聚合计算的,可以使用脚本来处理:
GET order/_search?size=0 { "runtime_mappings": { "product_and_brand": { "type": "keyword", "script": "emit(doc['product_name'].value + ' ' + doc['brand'].value)" } }, "aggs": { "product_brand_count": { "cardinality": { "field": "product_and_brand" } } } }
《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.21.Aggregations(5) https://developer.aliyun.com/article/1229239