《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.21.Aggregations(7) https://developer.aliyun.com/article/1229235
10、字符串统计聚合 string_stats
属于多值度量聚合,可用于计算统计聚合文档指定字段的字符串值的信息。字符串统计聚合包括:
l count 该字段非空的字符串数量
l min_length 最短的字符串长度
l max_length 最长的字符串长度
l avg_length 字符串的平均长度
l entropy 信息熵,量化了字段中包含的信息量,可用于度量数据集的广泛属性,如:多样性、相似性、随机性等
1)基础用法
POST /order/_search?size=0 { "aggs" : { "product_string_stats" : { "string_stats" : { "field" : "product_name" } } } }
输出结果:
{ ... "aggregations" : { "product_string_stats" : { "count" : 10, "min_length" : 6, "max_length" : 8, "avg_length" : 7.0, "entropy" : 3.469936429011566 } } }
在上述结果的基础上,我们向聚合文档中新增以下几个数据,并在添加完后立即执行 string_
stats:
PUT _bulk {"index":{"_index":"order","_id":11}} {"sales_name" : "Magi","product_name" : null,"brand" : "未知","count" : 2,"price" : 100,"order_time" : "2021-08-02"} {"index":{"_index":"order","_id":12}} {"sales_name" : "Magi","brand" : "未知","count" : 2,"price" : 100,"order_time" : "2021-08-02"} {"index":{"_index":"order","_id":13}} {"sales_name" : "Magi","product_name" : "","brand" : "未知","count" : 2,"price" : 100,"order_time" : "2021-08-02"
当前两条数据添加成功后,查看结果并未发生变化,当最后一条数据添加成功后,结果如下:
{ ... "aggregations" : { "product_string_stats" : { "count" : 11, "min_length" : 6, "max_length" : 8, "avg_length" : 6.363636363636363, "entropy" : 3.469936429011566 } } }
结果中的 count 和 avg_length 均发生了变化,也就是说空字符串会参与到 count 和avg_length 的计算中,其中 count 增加,avg_length 变小。
2)字符串分布
信息熵的计算是基于数据集字段中每个字符出现的概率,要想查看字符的概率分布,可以使用 show_distribution 参数,默认该值为 false。
POST /order/_search?size=0 { "aggs" : { "product_string_stats" : { "string_stats" : { "field" : "product_name", "show_distribution" : true } } } }
返回结果:
{ ... "aggregations" : { "product_string_stats" : { "count" : 11, "min_length" : 6, "max_length" : 8, "avg_length" : 6.363636363636363, "entropy" : 3.469936429011566, "distribution" : { "1" : 0.2, "e" : 0.14285714285714285, "a" : 0.07142857142857142, "h" : 0.07142857142857142, "i" : 0.07142857142857142, "m" : 0.07142857142857142, "n" : 0.07142857142857142, "o" : 0.07142857142857142, "p" : 0.07142857142857142, "t" : 0.07142857142857142, "2" : 0.04285714285714286, "0" : 0.02857142857142857, "3" : 0.014285714285714285 } } } }
由上述结果可以看出,返回的字符排序是按照字符出现的概率降序排列的。
3)缺失值
默认情况下,对于文档中统计字段中缺失值的情况下,这部分文档会被自动忽略掉,我们可以通过参数 missing 指定值,以下例子将对于 price 字段没有值的文档,默认按照 unknown 进行处理:
POST /order/_search?size=0 { "aggs" : { "product_string_stats" : { "string_stats" : { "field" : "product_name", "missing" : "unknown" } } } }
4)脚本
将产品名和品牌组合后再进行聚合统计:
GET order/_search?size=0 { "runtime_mappings": { "product_and_brand": { "type": "keyword", "script": """ emit(doc['product_name'].value + ' ' + doc['brand'].value) """ } }, "aggs": { "message_stats": { "string_stats": { "field": "product_and_brand" } } } }
11、普通脚本聚合
ES 默认使用 painless 脚本,基本用法:
"aggs" : { "<aggs_name>" : { "<aggs_type>" : { "script" : "<todo...>" 859 > 三、产品能力 } } }
l aggs_name:自定义聚合名
l aggs_type:聚合类型
l todo:脚本处理的逻辑
通过脚本聚合获取销售名为 Andy 的销售数量:
GET order/_search?size=0 { "aggs" : { "sum_count" : { "sum": { "script": "doc.sales_name.value == 'Andy' ? doc['count'].value :0" } } } }
12、脚本聚合scripted_metric
使用脚本进行度量聚合的输出,基础语法:
GET order/_search?size=0 { "query": { "match_all": {} }, "aggs": { "profit": { "scripted_metric": { "init_script": "<todo...>", "map_script": "<todo...>", "combine_script": "<todo...>", "reduce_script": "<todo...>" } } } }
1)脚本的范围
l init_script
l 初始化脚本,可用于在 state 对象中定义初始化全局变量(比如一个数组),在后续的 map_script 中处理的结果将被存放在该变量结构中。脚本对象的类型仅支持 string,map,array。
l map_script
l 该参数为必须的,定义了获取数据的规则,对分片上的每条数据执行。在未指定 combine_script 时,则结果状态需要存储在 state 对象中。
l combine_script
l 该参数为必须的,根据匹配出来的文档结果按照一定的规则进行组合后确定最后需要返回的数据。
l reduce_script
l 该参数为必须的,在每个分片上,根据 combine_script 中返回的数据结果(该结果以数组的方式存储在变量 states 中)进行汇总,作为最后的结果输出。
举例:
l init_script 定义数组变量 orders
l map_script 将品牌名为 “ABC” 的价格计入 orders 变量中
l combine_script 对分片的结果乘以0.8后加和汇总
l reduce_script 将所有分片的结果加和输出
GET order/_search?size=0 { "query": { "match_all": {} }, "aggs": { "discount_price": { "scripted_metric": { "init_script": "state.orders = []", "map_script": "state.orders.add(doc.brand.value == 'Apple' ? doc.price.value :0)", "combine_script": "double price = 0; for (t in state.orders) { price += t*0.8 } return price", "reduce_script": "double price = 0; for (a in states) { price += a } return price" } } } }
返回结果:
{ ... "aggregations" : { "discount_price" : { "value" : 34841.064000000006 } 862 > 三、产品能力 } }
以上脚本的执行过程可参考下图:
《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.21.Aggregations(9) https://developer.aliyun.com/article/1229232