顿搜
09. ES Metrics聚合——ElasticSearch搜索专栏
Metrics聚合是基于从正在聚合的文档中以一种或另一种方式提取的值来计算度量
一、计算加权平均值
计算加权平均值是通过weighted_avg选项的参数来进行处理的
POST /dbindex/_search
{
"size": 0,
"aggs": {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade" // 计算grade字段的加权平均值
},
"weight": {
"field": "weight"
}
}
}
}
}返回结果
{
"aggregations" : {
"weighted_grade" : {
"value" : 75.99999985098839 // 加权平均值
}
}
}在实际业务中,有可能出现索引结构不一致的情况,那么需要在“运行时字段”上进行聚合
POST /dbindex/_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" // 在"运行时字段"上进行聚合统计,查询加权平均值
},
"weight": {
"field": "weight.combined"
}
}
}
}
}返回结果
{
"aggregations" : {
"weighted_grade" : {
"value" : 86.25
}
}
}((902)+(903)+(80*3))/(2+3+3)=86.25
二、去重后求总数量
若需要去重后求总数量,则通过cardinality选项的参数来进行处理
POST /dbindex/_search
{
"size":0,
"aggs": {
"type_count": {
"cardinality": {
"field": "name.keyword" // 统计计算不重名的姓名总数量
}
}
}
}返回结果
{
"aggregations" : {
"type_count" : {
"value" : 2
}
}
}三、绝对中位差
绝对中位差是用原数据减去中位数后得到的新数据的绝对值之中位数,使用median_absolute_deviation关键字进行统计
GET /dbindex/_search
{
"size": 0,
"aggs": {
"review_average": {
"avg": {
"field": "price"
}
},
"review_variability": {
"median_absolute_deviation": { // 计算价格的绝对中位数
"field": "price"
}
}
}
}返回结果
{
"aggregations" : {
"review_average" : {
"value" : 70 // 绝对中位数
},
"review_variability" : {
"value" : 10 // 变异系数
}
}
}四、最大值、最小值、平均值
可以使用stats关键字一次性统计出最大值、最小值、平均值、总和、总条数等信息
POST dbindex/_search
{
"size":0,
"aggs":{
"grades_stats":{
"stats":{ // 查询grade字段的最大值、最小值、平均值、总和、总条数等信息
"field":"grade"
}
}
}
}返回结果
{
"aggregations" : {
"grades_stats" : {
"count" : 3,
"min" : 60.0,
"max" : 90.0,
"avg" : 76.66666666666667,
"sum" : 230.0
}
}
}以上结果使用stats关键字一次性统计出最大值、最小值等信息。
如果想要统计其他扩展状态值,可以使用extended_stats关键字进行统计
POST dbindex/_search
{
"size":0,
"aggs":{
"grades_stats":{
"extended_stats":{
"field":"grade"
}
}
}
}返回结果
{
"aggregations" : {
"grades_stats" : {
"count" : 3,
"min" : 60.0,
"max" : 90.0,
"avg" : 76.66666666666667,
"sum" : 230.0,
"sum_of_squares" : 18100.0,
"variance" : 155.55555555555597,
"variance_population" : 155.55555555555597,
"variance_sampling" : 233.33333333333394,
"std_deviation" : 12.472191289246489, // 标准差
"std_deviation_population" : 12.472191289246489,
"std_deviation_sampling" : 15.275252316519486,
"std_deviation_bounds" : {
"upper" : 101.61104924515965,
"lower" : 51.722284088173694,
"upper_population" : 101.61104924515965,
"lower_population" : 51.722284088173694,
"upper_sampling" : 107.21717129970564,
"lower_sampling" : 46.1161620336277
}
}
}
}五、字符串统计
统计字符串的长度等信息,可以使用string_stats关键字进行统计
POST dbindex/_search
{
"size":0,
"aggs":{
"message_stats":{
"string_stats":{ // 聚合统计body.keyword字段中内容的长度
"field":"body.keyword"
}
}
}
}返回结果
{
"aggregations" : {
"message_stats" : {
"count" : 3,
"min_length" : 19,
"max_length" : 35,
"avg_length" : 27.0,
"entropy" : 3.987274621250932
}
}
}以上结果返回了所有文档中对应字段的内容最大长度、最小长度等信息。
六、百分位数统计
统计百分位数,可以使用percentiles关键字进行统计
GET dbindex/_search
{
"size": 0,
"aggs": {
"age_outlier": {
"percentiles": { // 计算索引库中age字段的百分位数
"field": "age"
}
}
}
}返回结果
{
"aggregations" : {
"age_outlier" : {
"values" : {
"1.0" : 18.000000000000004,
"5.0" : 18.0,
"25.0" : 18.5,
"50.0" : 19.5,
"75.0" : 20.5,
"95.0" : 21.0,
"99.0" : 21.0
}
}
}
}百分位度量标准将生成一定范围的百分位数:[1,5,25,50,75,95,99]。
如果需要指定计算的百分位数,可以使用如下语句
GET dbindex/_search
{
"size": 0,
"aggs": {
"age_outlier": {
"percentiles": {
"field": "age",
"percents": [
50,
95,
99
]
}
}
}
}返回结果
{
"aggregations" : {
"age_outlier" : {
"values" : {
"50.0" : 19.5,
"95.0" : 21.0,
"99.0" : 21.0
}
}
}
}以上结果只返回了"50","95"",99"的百分位数
七、百分位等级计算
根据指定的数值计算出数值对应的百分位等级
GET dbindex/_search
{
"size": 0,
"aggs": {
"age_ranks": {
"percentile_ranks": { // 计算age字段值等于30和50的百分位等级
"field": "age",
"values": [ 30, 50 ]
}
}
}
}返回结果
{
"aggregations" : {
"age_ranks" : {
"values" : {
"30.0" : 50.0,
"50.0" : 100.0
}
}
}
}以上结果, 30岁在所有年龄数据中属于百分之五十分位,50岁在所有年龄数据中属于百分之百分位
八、聚合后返回前N条数据
利用top_hits关键字在聚合后在每一个Bucket中仅返回指定顺序的前N条数据
#根据address字段进行聚合,再根据age字段倒序输出,输出每一个地址中age字段值排名前1的数据
POST /dbindex/_search?size=0
{
"aggs": {
"top_tags": { // 第一层聚合:先按照address.keyword将数据聚合成多个Bucket(聚合桶)
"terms": {
"field": "address.keyword"
},
"aggs": {
"top_sales_hits": {
"top_hits": { // 第二层聚合:在第一层聚合结果中的每个Bucket内进行top_hits操作
"sort": [
{
"age": { // 排序条件按照age倒序
"order": "desc"
}
}
],
"_source": { //只返回name和age字段的值
"includes": [ "name", "age" ]
},
"size": 1 // 仅返回前1条记录
}
}
}
}
}
}返回结果
{
"aggregations" : {
"buckets" : [
{
"key" : "美国",
"doc_count" : 3,
"hits" : [
{
"_source" : {
"name" : "李白",
"age" : 50
},
"sort" : [
50
]
}
]
},
{
"key" : "中国",
"doc_count" : 2,
"top_sales_hits" : {
"hits" : [
{
"_index" : "myindex_percentile_ranks",
"_source" : {
"name" : "李四",
"age" : 20
},
"sort" : [
20
]
}
]
}
}
]
}
}九、top_metrics聚合
top_metrics关键字与top_hits关键字非常相似,但它能够使用更少的内存来完成聚合,性能更高
POST /dbindex/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": { // 获取索引库中num字段的最大值和对应的score信息
"metrics": {"field": "score"},
"sort": {"num": "desc"}
}
}
}
}返回结果
{
"aggregations" : {
"tm" : {
"top" : [
{
"sort" : [
3
],
"metrics" : {
"score" : 2.718280076980591
}
}
]
}
}
}如果需要返回结果中靠前的多个文档,可以设置size字段
POST /dbindex/_search?filter_path=aggregations
{
"aggs": {
"tm": {
"top_metrics": {
"metrics": {"field": "score"},
"sort": {"num": "desc"},
"size":2
}
}
}
}返回结果
{
"aggregations" : {
"tm" : {
"top" : [
{
"sort" : [3],"metrics" : {"score" : 2.718280076980591}
},
{
"sort" : [2],"metrics" : {"score" : 1.0}
}
]
}
}
}以上结果中,根据num字段进行排序,返回前两条文档数据