es搜索 核心指标_Elasticsearch(8) --- 聚合查询(Metric聚合)

聚合查询(Metric聚合)

说明:该博客对于的Elasticsearch 的版本为7.3。

在Mysql中,我们可以获取一组数据的 最大值(Max)、最小值(Min)。同样我们能够对这组数据进行 分组(Group)。那么对于Elasticsearch中

我们也可以实现同样的功能,聚合有关资料官方文档内容较多,这里大概分两篇博客写这个有关Elasticsearch聚合。

官方对聚合有四个关键字: Metric(指标)、Bucketing(桶)、Matrix(矩阵)、Pipeline(管道)。

一、聚合概念

1. ES聚合分析是什么?

概念 Elasticsearch除全文检索功能外提供的针对Elasticsearch数据做统计分析的功能。它的实时性高,所有的计算结果都是即时返回。

Elasticsearch将聚合分析主要分为如下4类:

Metric(指标): 指标分析类型,如计算最大值、最小值、平均值等等 (对桶内的文档进行聚合分析的操作)

Bucket(桶): 分桶类型,类似SQL中的GROUP BY语法 (满足特定条件的文档的集合)

Pipeline(管道): 管道分析类型,基于上一级的聚合分析结果进行在分析

Matrix(矩阵): 矩阵分析类型(聚合是一种面向数值型的聚合,用于计算一组文档字段中的统计信息)

2.ES聚合分析查询的写法

在查询请求体中以aggregations节点按如下语法定义聚合分析:

"aggregations" : {

"" : {

"" : {

}

[,"meta" : { [] } ]?

[,"aggregations" : { []+ } ]?

}

[,"" : { ... } ]*

}

说明:aggregations 也可简写为 aggs

3、指标(metric)和 桶(bucket)

虽然Elasticsearch有四种聚合方式,但在一般实际开发中,用到的比较多的就是Metric和Bucket。

(1) 桶(bucket)

a、简单来说桶就是满足特定条件的文档的集合。

b、当聚合开始被执行,每个文档里面的值通过计算来决定符合哪个桶的条件,如果匹配到,文档将放入相应的桶并接着开始聚合操作。

c、桶也可以被嵌套在其他桶里面。

(2)指标(metric)

a、桶能让我们划分文档到有意义的集合,但是最终我们需要的是对这些桶内的文档进行一些指标的计算。分桶是一种达到目的地的手段:它提供了一种给文档分组的方法来让

我们可以计算感兴趣的指标。

b、大多数指标是简单的数学运算(如:最小值、平均值、最大值、汇总),这些是通过文档的值来计算的。

二、指标(Metric)详解

官网: 指标聚合官网文档:Metric

Metric聚合分析分为单值分析和多值分析两类:

#1、单值分析,只输出一个分析结果

min,max,avg,sum,cardinality

#2、多值分析,输出多个分析结果

stats,extended_stats,percentile,percentile_rank,top hits

1、Avg(平均值)

计算从聚合文档中提取的数值的平均值。

POST /exams/_search?size=0

{

"aggs" : {

"avg_grade" : { "avg" : { "field" : "grade" } }

}

}

2、Max(最大值)

计算从聚合文档中提取的数值的最大值。

POST /sales/_search?size=0

{

"aggs" : {

"max_price" : { "max" : { "field" : "price" } }

}

}

3、Min(最小值)

计算从聚合文档中提取的数值的最小值。

POST /sales/_search?size=0

{

"aggs" : {

"min_price" : { "min" : { "field" : "price" } }

}

}

4、Sum(总和)

计算从聚合文档中提取的数值的总和。

POST /sales/_search?size=0

{

"query" : {

"constant_score" : {

"filter" : {

"match" : { "type" : "hat" }

}

}

},

"aggs" : {

"hat_prices" : { "sum" : { "field" : "price" } }

}

}

5、 Cardinality(唯一值)

cardinality 求唯一值,即不重复的字段有多少(相当于mysql中的distinct)

POST /sales/_search?size=0

{

"aggs" : {

"type_count" : {

"cardinality" : {

"field" : "type"

}

}

}

}

6、Stats

stats 统计,请求后会直接显示多种聚合结果

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

}

}

}

7、Percentiles

对指定字段的值按从小到大累计每个值对应的文档数的占比,返回指定占比比例对应的值。

1)默认取百分比

默认按照[ 1, 5, 25, 50, 75, 95, 99 ]来统计

GET latency/_search

{

"size": 0,

"aggs" : {

"load_time_outlier" : {

"percentiles" : {

"field" : "load_time"

}

}

}

}

返回结果可以理解为:占比为50%的文档的age值 <= 445,或反过来:age<=445的文档数占总命中文档数的50%

{

...

"aggregations": {

"load_time_outlier": {

"values" : {

"1.0": 5.0,

"5.0": 25.0,

"25.0": 165.0,

"50.0": 445.0,

"75.0": 725.0,

"95.0": 945.0,

"99.0": 985.0

}

}

}

}

2)指定分位值

GET latency/_search

{

"size": 0,

"aggs" : {

"load_time_outlier" : {

"percentiles" : {

"field" : "load_time",

"percents" : [95, 99, 99.9]

}

}

}

}

Keyed Response

默认情况下,keyed标志设置为true,它将唯一的字符串键与每个存储桶相关联,并将范围作为哈希而不是数组返回。

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

}

]

}

}

}

8、 Percentile Ranks

上面是通过百分比求文档值,这里通过文档值求百分比。

GET latency/_search

{

"size": 0,

"aggs" : {

"load_time_ranks" : {

"percentile_ranks" : {

"field" : "load_time",

"values" : [500, 600]

}

}

}

}

返回结果

{

...

"aggregations": {

"load_time_ranks": {

"values" : {

"500.0": 55.1,

"600.0": 64.0

}

}

}

}

结果说明:时间小于500的文档占比为55.1%,时间小于600的文档占比为64%,

9、Top Hits

一般用于分桶后获取该桶内匹配前n的文档列表

POST /sales/_search?size=0

{

"aggs": {

"top_tags": {

"terms": {

"field": "type", #根据type进行分组 每组显示前3个文档

"size": 3

},

"aggs": {

"top_sales_hits": {

"top_hits": {

"sort": [

{

"date": {

"order": "desc" #按照时间进行倒叙排序

}

}

],

"_source": {

"includes": [ "date", "price" ] #只显示文档指定字段

},

"size" : 1

}

}

}

}

}

}

三、示例

下面会针对上面官方文档的例子进行举例说明。

1、添加测试数据

1)创建索引

DELETE /employees

PUT /employees/

{

"mappings" : {

"properties" : {

"age" : {

"type" : "integer"

},

"gender" : {

"type" : "keyword"

},

"job" : {

"type" : "text",

"fields" : {

"keyword" : {

"type" : "keyword",

"ignore_above" : 50

}

}

},

"name" : {

"type" : "keyword"

},

"salary" : {

"type" : "integer"

}

}

}

}

2)添加数据

添加10条数据,每条数据包含:姓名、年龄、工作、性别、薪资

PUT /employees/_bulk

{ "index" : { "_id" : "1" } }

{ "name" : "Emma","age":32,"job":"Product Manager","gender":"female","salary":35000 }

{ "index" : { "_id" : "2" } }

{ "name" : "Underwood","age":41,"job":"Dev Manager","gender":"male","salary": 50000}

{ "index" : { "_id" : "3" } }

{ "name" : "Tran","age":25,"job":"Web Designer","gender":"male","salary":18000 }

{ "index" : { "_id" : "4" } }

{ "name" : "Rivera","age":26,"job":"Web Designer","gender":"female","salary": 22000}

{ "index" : { "_id" : "5" } }

{ "name" : "Rose","age":25,"job":"QA","gender":"female","salary":18000 }

{ "index" : { "_id" : "6" } }

{ "name" : "Lucy","age":31,"job":"QA","gender":"female","salary": 25000}

{ "index" : { "_id" : "7" } }

{ "name" : "Byrd","age":27,"job":"QA","gender":"male","salary":20000 }

{ "index" : { "_id" : "8" } }

{ "name" : "Foster","age":27,"job":"Java Programmer","gender":"male","salary": 20000}

{ "index" : { "_id" : "9" } }

{ "name" : "Gregory","age":32,"job":"Java Programmer","gender":"male","salary":22000 }

{ "index" : { "_id" : "10" } }

{ "name" : "Bryant","age":20,"job":"Java Programmer","gender":"male","salary": 9000}

2、求薪资最低值

POST employees/_search

{

"size": 0,

"aggs": {

"min_salary": {

"min": {

"field":"salary"

}

}

}

}

返回

3、找到最低、最高和平均工资

POST employees/_search

{

"size": 0,

"aggs": {

"max_salary": {

"max": {

"field": "salary"

}

},

"min_salary": {

"min": {

"field": "salary"

}

},

"avg_salary": {

"avg": {

"field": "salary"

}

}

}

}

4、一个聚合,输出多值

POST employees/_search

{

"size": 0,

"aggs": {

"stats_salary": {

"stats": {

"field":"salary"

}

}

}

}

返回

5、求一共有多少工作类型

POST employees/_search

{

"size": 0,

"aggs": {

"cardinate": {

"cardinality": {

"field": "job.keyword"

}

}

}

}

返回

注意 我们需要把job的类型为keyword类型,这样就不会分词,把它当成一个整体。

6、查看中位数的薪资

POST employees/_search

{

"size": 0,

"aggs": {

"load_time_outlier": {

"percentiles": {

"field": "salary",

"percents" : [50, 99],

"keyed": false

}

}

}

}

返回

发现这些工作的中位数是:21000元。

7、取每个工作类型薪资最高的数据

多层嵌套 根据工作类型分桶,然后按照性别分桶,计算每个桶中工资的最高的薪资。

POST employees/_search

{

"size": 0,

"aggs": {

"Job_gender_stats": {

"terms": {

"field": "job.keyword"

},

"aggs": {

"gender_stats": {

"terms": {

"field": "gender"

},

"aggs": {

"salary_stats": {

"max": {

"field": "salary"

}

}

}

}

}

}

}

}

返回

参考

1、Elasticsearch核心技术与实战---阮一鸣(eBay Pronto平台技术负责人

我相信,无论今后的道路多么坎坷,只要抓住今天,迟早会在奋斗中尝到人生的甘甜。抓住人生中的一分一秒,胜过虚度中的一月一年!(12)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值