这篇分析ELK聚集查询之指标聚集和单通聚集:
聚集查询
(Aggregation)
提供了针对多条文档的统计运算功能,它不是针对文 档本身内容的检索,而是要将它们聚合到一起运算某些方面的特征值。 聚集查询与 SQL
语言中的聚集函数非常像,聚集函数在
Elasticsearch
中相当 于是聚集查询的一种聚集类型。 比如在 SQL
中的
avg
函数用于求字段平均值, 而在 Elasticsearch
中要实现相同的功能可以使用
avg
聚集类型。 聚集查询也是通过_search
接口执行,只是在执行聚集查询时使用的参数是 aggregations 或
aggs
。所以
_search
接口可以执行两种类型的查询,
1
种是通过 query 参数执行
DSL
,另一种则是通过
aggregations
执行聚集查询。 这两种查询方式还可以放在一起使用, 执行逻辑是先通过 DSL
检索满足查 询条件的文档,然后再使用聚集查询对 DSL
检索结果做聚集运算这一规则适用 于本章列举的所有聚集查询。聚集查询有着比较规整的请求结构,具体格式如下:
"aggregations/aggs" : {
"<
聚集名称
>":{
"<
聚集类型
>":{
<
聚集体
>
}
………
[,"aggregations/aggs" : ( [ <
子聚集
>]+ ) ]
}
[,"<
聚集名称
>
”
: (...) ]*
}
aggregations
和
aggs
都是
_search
的参数,其中
aggs
是
agregations
的简写。 每一个聚集查询都需要定义一个聚集名称,并归属于种聚集类型。聚集名称是用 户自定义的, 而聚集类型则是由 Elasticsearch
预先定义好。 聚集名称会在返回结果中标识聚集结果,而聚集类型则决定了聚集将如何运 算。比如前面提到的 avg
就是一种聚集类型。 这里要特别强调的是,聚集中可
以再包含子聚集。子聚集位于父聚集的名称中,与聚集类型同级,所以子聚集的 运算都是在父聚集的环境中运算。Eaticsarch
对子聚集的深度没有限制,所以理 论上说可以包含无限深度的子聚集。 聚集类型总体上被分为四种大类型,即指标聚集(MetricsAggregation)
、 桶 型( Bucket Aggregation)
、管道聚集
( Pipeline Aggregation)
和矩阵聚集
( Matrix Aggregation)。 指标聚集是根据文档字段所包含的值运算某些统计特征值,如平均值、总和 等,它们的结果一般都包含一个或多个数值,前面提到的 avg
聚集就是指标聚集 的 1
种。桶型聚集根据一定的分组标准将文档归到不同的组中,这些分组在 Elasticsearch 中被称为桶
( Bucken)
,桶型聚集与
SQL
中
group by
的作用类似,一 般会与指标聚集嵌套使用。管道聚集可以理解为聚集结果的再聚集,它一般以另 一个聚集结果作为输人,然后在此基础上再做聚集。矩阵聚集是 Elasticsearch
中 的新功能,由于是针对多字段做多种运算,所以形成的结果类似于矩阵。
1、指标聚集
指标聚集是根据文档中某一字段做聚集运算,比如计算所有产品销量总和、 平均值等等。指标聚集的结果可能是单个值,这种指标聚集称为单值指标聚集; 也可能是多个值,称为多值指标聚集。
2、平均值聚集
平均值聚集是根据文档中数值类型字段计算平均值的聚集查询,包括
avg
聚 集和 weighted_avg
聚集两种类型。
avg
聚集直接取字段值后计算平均值,而 weighted _avg 聚集则会在计算平均值时添加不同的权重。
3、avg
聚集
avg
聚集计算平均值,例如在示例中计算航班的平均延误时间:
POST /kibana_sample_data_flights/_search ?filter_path=aggregations
{
"aggs": {
"delay_avg": {
"avg": {"field": "FlightDelayMin"}
}
}
}
在示例
7-2
中使用了请求参数
fiter _path
将返回结果的其他字段过滤掉了, 否则查询的结果中将包含 kibana_sample_data_flights
索引中的文档。加了 filter_path 之后返果为
:
在返回结果中,
aggregations
是关键字,代表这是聚集查询的结果。其中的 delay_avg 则是在聚集查询中定义的聚集名称,
value
是聚集运算的结果。 在示例中运算航班延误时间时会将所有文档都包含进来做计算,如果只想其 中一部分文档参与运算则可以使用 query
参数以
DSL
的形式定义查询条件。 例如在示例中就是只计算了飞往中国的航班平均延误时间:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"match": {
"DestCountry": "CN"
}
},
"aggs": {
"delay_avg": {
"avg": {"field": "FlightDelayMin"}
}
}
}
在示例中请求
_search
接口时,同时使用了
query
与
aggs
参数。在执行检索 时会先通过 query
条件过滤文档,然后再在符合条件的文档中运算平均值聚集。 weighted_avg 无非就是根据某些条件对进行聚集的数据进行加权运算,和 avg 聚集没有本质差别。
4、计数聚集与极值聚集
计数聚集用于统计字段值的数量,而极值聚集则是查找字段的极大值和极小 值。
5、计数聚集
value_count
聚集和
cardinality
聚集可以归入计数聚集中,前者用于统计从 字段中取值的总数,而后者则用于统计不重复数值的总数。例如:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"country_code": {
"cardinality": {"field": "DestCountry"}
},
"total_country": {
"value_count": {"field": "DestCountry"}
}
}
}
在示例中,
cardinality
聚集统计了
DestCountry
字段非重复值的数量,类似 于 SQL
中的
distinct
。
value_count
聚集则统计了
DestCountry
字段所有返回值的 数量,类似于 SQL
中的
count
。 需要注意的是,cardinality
聚集的算法使用极小内存实现统计结果的基本准 确。所以 cardinality
在数据量极大的情况下是不能保证完全准确的。
6、极值聚集
极值聚集是在文档中提取某一字段最大值或最小值的聚集,包括
max
聚集 和 min
聚集。
例如
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"max_price": {
"max": {"field": "AvgTicketPrice"}
},
"min_price":{
"min": {"field": "AvgTicketPrice"}
}
}
}
上面例子聚集有
max_price
和
min_price
两个,它们分别计算了机票价格的 最大的最小值。
7、统计聚集
统计聚集是一个多值指标聚集,也就是返回结果中会包含多个值,都是一些 与统计相生的数据。统计聚集包含 stats
聚集和
extended_stats
聚集两种,前者 返回的统计数据是一些比较基本的数值,而后者则包含一些比较专业的统计数值。
8、stats
聚集
stats
聚集返回结果中包括字段的最小值
(min)
、 最大值
(max)
、总和
(sum)
、 数业(coun)
及平均值
(avg)
五项内容。例如,在示例
7-9
中对机票价格做统计
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"price_stats": {
"stats": { "field": "AvgTicketPrice" }
}
}
}
在示例中,
stats
聚集使用
field
参数指定参与统计运算的字段为 AvgTicketPrice。
9、extended_stats
聚集
extended_stats
聚集增加了几项统计数据,这包括平方和、方差、标准方差 和标准方差偏移量。从使用的角度来看,extended_stats
聚集与
stats
聚集完全 相同,只是聚集类型不同。
10、百分位聚集
百分位聚集根据文档字段值统计字段值按百分比的分布情况,包括 pecrentiles 聚集和
percentile_ranks
两种。前者统计的是百分比与值的对应关系, 而后者正好相反统计值与百分比的对应关系。
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"price_percentile": {
"percentiles": {"field": "AvgTicketPrice", "percents": [25,50,75,100]}
},
"price_percentile_rank": {
"percentile_ranks": {"field": "AvgTicketPrice", "values": [600,1200]}
}
}
}
pecrentiles
聚集通过
pecrents
参数设置组百分比,然后按值由小到大的顺序 划分不同区间,每个区间对应一个百分比。percentile_ranks
聚集则通过
value
参 数设置组值, 然后根据这些值分别计算落在不同值区间的百分比。
以示例返回的结果为例
:
在
pecrentiles
返回结果
price_percentile
中,“
"25. 0" : 410. 0127977258341" 代表的含义是 25%
的机票价格都小于
410. 0127977258341
,其他以此类推。在 percentile_ranks 返回结果
price_percentile_rank
中,
600.0": 45. 39892372745635"代表的含义是
600.0
以下的机票占总机票价格的百分比为 45.39892372745635%。
11、使用范围分桶
如果使用
SQL
语言类比,桶型聚集与
SQL
语句中的
group by
子句极为相似。 桶型聚集(Bucket Aggregation)
是
Elasticsearch
官方对这种聚集的叫法,它起的作 用是根据条件对文档进行分组。 可以将这里的桶理解为分组的容器,每个桶都与一个分组标准相关联,满足 这个分组标准的文档会落桶中。所以在默认情况下,桶型聚集会根据分组标准返 回所有分组,同时还会通过 doc_count
字段返回每一桶中的文档数量。 由于单纯使用桶型聚集只返回桶内文档数量,意义并不大,所以多数情况下 都是将桶型聚集与指标聚集以父子关系的形式组合在起使用。桶型聚集作为父聚 集起到分组的作用。而指标聚集则以子聚集的形式出现在桶型聚集中, 起到分 组统计的作用。比如将用户按性别分组,然后统计他们的平均年龄。按返回桶的数量来看,桶型聚集可以分为单桶聚集和多桶聚集。在多桶聚集 中,有些桶的数量的固定的。而有些桶的数量则是在运算时动态决定。由于桶聚 集基本都是将所有桶一次返回,返回了过多的通会影响性能,所以单个请求允许 返间的最大桶数受 search.max_bucket 参数限制。 这个参数在 7.0
之前的版本中默认值为
-1
,代表无上限。但在
Elasticsearch 版本 7
中,这个参数的默认值已经更改为
10000
所以在做桶型聚集时要先做好数 据验证,防止桶数量过多影响性能。
桶型聚集的种类非常多,我们分别来讲解。
12、数值范围
range
、
date_range
与
ip_range
这三种类型的聚集都用于根据字段的值范围 内对文档分桶,字段值在同一范围内的文档归入同一桶中。每个值范围都可通过 from 和
to
参数指定,范围包含
from
值但不包含
to
值,用数学方法表示就是
[from, to)。 在设置范围时,可以设置一个也可以设置多个,范围之间并非一定要连续, 可以有间隔也可以有重叠。
13、range
聚集
range
聚集使用
ranges
参数设置多个数值范围,使用
field
参数指定
1
个数值 类型的字段。range
聚集在执行时会将该字段在不同范围内的文档数量统计出来, 并在返回结果的 doc_count
字段中展示出来。例如统计航班不同范围内的票价数
量,可以按示例的方式发送请求
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"price_ranges":{
"range":{
"field": "AvgTicketPrice" ,
"ranges":[
{"to": 300 },
{"from": 300,"to": 600 },
{"from": 600,"to": 900 },
{"to": 900 }
]
}
}
}
}
在返回结果中,每个范围都会包含一个
key
字段,代表了这个范围的标识, 它的基本格式是“<from>- <to>"。如果觉得返回的这种
key
格式不容易理解,可 以通过在 range
聚集的请求中添加
keyed
和
key
参数定制返回结果的
key
字段值。 其中 keyed
是
range
的参数,用于标识是否使用
key
标识范围,所以为布尔类型, key 参数则是与
from
、
to
参数同级的参数,用于定义返回结果中的
key
字段值。
14、date_range
聚集
date_range
聚集与
range
聚集类似,只见范围和字段的类型为日期而非数值 date_range 聚集的范围指定也是通过
ranges
参数设置,具体的范围也是使 用<from>- <to>
两个参数,并且可以使用
keyed
和
key
定义返回结果的标识。 date_range 聚集多了个指定日期格式的参数
format,
可以用于指定
from
和
to
的 目期格式。例如,
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"mar_flights": {
"date_range":{
"field": "timestamp",
"ranges":[
{"from": "2019-03-01","to": "2019-03-30" }
],
"format": "yyyy-MM-dd"
}
}
}
}
15、ip_range
聚集
ip_ range
聚集根据
ip
类型的字段统计落在指定
IP
范围的文档数量,使用的 聚集类型名称为 ip_ range
。例如,统计了两个
IP
地址范围的文档数量
:
POST /kibana_sample_data_logs/_search?filter_path=aggregations
{
"aggs":{
"local":{
"ip_range": {
"field": "clientip",
"ranges":[
{"from": "157.4.77.0", "to": "157.4.77.255"},
{"from": "105.32.127.0", "to": "105.32.127.255"}
]
}
}
}
}
16、间隔范围
histogram
、
date _ histogram
与
auto_date_histogram
这三种聚集与上一节中 使用数值定义范围的聚集很像,也是统计落在某一范围内的文档数量。 但与数 值范围聚集不同的是,这三类座集统计范围由固定的间隔定义,也就是范围的结
束值和起始值的差值是固定的。
17、histogram
聚集
histogram
聚集以数值为间隔定义数值范围,字段值具有相同范围的文档将 落入同桶中。例如示例以 100
为间隔做分桶,可以通过返回结果的
doc_count
字 段获取票价在每个区间的文档数量:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"price_histo": {
"histogram": {
"field": "AvgTicketPrice",
"interval": 100,
"offset":50 ,
"keyed": false,
"order": {
"_count": "asc"
}
}
}
}
}
其中,
interval
参数用于指定数值问隔必须为正值,而
offset
参数则代表起 始数值的偏移量,必须位于[0, interval)
范围内。
order
参数用于指定排序字段和
顺序,可选字段为
_key
和
_count
。当
keyed
参数设置为
true
时,返回结果中每 个桶会有一个标识,标识的计算公式为 bucket_key = Math. floor( ( value- offset)/interval) * interval + offset。
18、date_histogram
聚集
date_histogra
聚集以时间为间隔定义日期范围,字段值具有相同日期范围的 文档将落入同一桶中。同样,返回结果中也会包含每个间隔范围内的文档数量 doc_count。 例如统计每月航班数量
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"month flights": {
"date_histogram": {"field": "timestamp", "interval": "month"}
}
}
}
在示例使用参数
interval
指定时间间隔为
month,
即按月划分范围。时间可以 是还有:
毫秒:1ms 10ms
秒:
second/1s 10s
分钟:
minute/1m 10m
小时:
hout/1h 2h
天:
day 2d
不支持
星期:
week/1w
不支持
月:
month/1M
不支持
季度:
quarter/1q
不支持
年:
year/1y
不支持
不过这个参数将要过期,替代的是
fixed_interval
和
calendar_interval
,可以 参考这个页面,有详细说明:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregatio
ns-bucket-datehistogram-aggregation.html
简单来说,
calendar_interval
支持
1
年、
1
季度、
1
月、
1
周、
1
天、
1
小时、 1 分钟,不支持时间为复数,
fixed_interval
支持的时间单位为天、小时、分、秒、 毫秒,允许复数,例如"fixed_interval" : "30d"
,表示为
30
天。
19、auto_date_histogram
聚集
前述两种聚集都是指定间隔的具体值是多少,然后再根据间隔值返回每一 桶中满足条件的文档数。最终会有多少桶取决于两个条件,即间隔值和字段值在所有文档中的实际跨度。反过来,如果预先指定需要返回多少个桶,那么间隔值 也可以通过桶的数量以及字段值跨度共同确定。auto_date_histogram 聚集就是这 样一种聚集,它不是指定时间间隔值,而是指定需要返回桶的数量。例如在示例 中定义需要返回 10
个时间段的桶
:
POST /kibana_sample_data_flights/_search?size=0
{
"aggs":{
"age_group" : {
"auto_date_histogram" : {
"field": "timestamp",
"buckets" :10
}
}
}
}
参数
field
设置通过哪一个字段做时间分隔,而参数
buckets
则指明了需要返 回多少个桶。 默认情况下, buckets
的数量为
10
。需要注意的是,
buckets
只 是设置了期望返回桶的数量,但实际返回桶的数量可能等于也可能小于 buckets 设置的值。例如示例的请求中期望 10
个桶,但实际可能只返回
6
个桶。 auto_date_histogram 聚集在返回结果中还提供了一个
interval
字段,用于说
明实际采用的间隔时间。从实现的角度来说,不精确匹配
buckets
数量也有利于 提升检索的性能。
20、子聚集
(
聚集嵌套
)
前面介绍的桶型聚集,大部分都只是返回满足聚集条件的文档数量。在实际 应用中,如果需要桶型聚集与 SQL
中的
group by
具有相同的意义,用于将文档 分桶后计算各桶特定指标值,比如根据用户性别分组,然后分别求他们的平均年 龄。Elasticsearch
这样的功能通过子聚集
(
聚集嵌套
)
来实现。例如,示例中的请 求就是先按月对从中国起飞的航班做了分桶,然后又通过聚集嵌套计算每月平均 延误时间:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"term": {"OriginCountry": "CN"}
},
"aggs":
{
"date_price_histogram": {
"date_histogram": {
"field": "timestamp",
"interval": "month"
},
"aggs": {
"avg_price":
{
"avg": {
"field": "FlightDelayMin"
}
}
}
}
}
}
在示例中,
_search
接口共使用了两个参数,
query
参数以
term
查询条件将 所有 OriginCountry
字段是
CN
的文档筛选出来参与聚集运算。 aggs 参数则定义了一个名称为
data_price_histogram
的桶型聚集,这个聚集 内部又嵌套了个名称为 avg_ price
的聚集。由于
price
这个聚集位于
data_price histogram 中,所以它会使用这个聚集的分桶结果做运算而不会针对所有文档。
所以,最终的效果就是将按月计算从中国出发航班的平均延误时间, 使用嵌套聚集时要注意,嵌套聚集应该位于父聚集名称下而与聚集类型同级, 并且需要通过参数再次声明。如果与父聚集一样位于 aggs
参数下,那么这两个 聚集就是平级而非嵌套聚集。
21、使用词项分桶
使用字段值范围分桶主要针对结构化数据,比如年龄、
IP
地址等等。但对 于字符串类型的字段来说,使用值范围来分桶显然是不合适的。由于字符串类型 字段在编入索引时会通过分析器生成词项,所以字符申类型字段的分桶一般通过 词项实现。使用词项实现分桶的聚集,包括 terms
、
significant_terms
和 significant_text 聚集。由于使用词项分桶需要加载所有词项数据,所以它们在执 行速度上都会比较慢。为了提升性能,Elsticesearch
提供了
sampler
和diversifed_sampler 聚集,可通过缩小样本数量减少运算量。
22、terms
聚集
terms
聚集根据文档字段中的词项做分桶,所有包含同一词项的文档将被归 人同一桶中,聚集结果中包含字段中的词项及其词频,在默认情况下还会根据词 频排序,所以 terms
聚集也可用于热词展示,由于
terms
聚集在统计词项的词频
数据时需要打开它的
fielddata
机制。fielddata 机制对内存消耗较大且有导致内存 溢出的可能, 所以 terms
聚集一般针对
keyword
非
text
类型。
Fielddata
:其实根据倒排索引反向出来的一个正排索引,即
document
到
term
的映射。
只要我们针对需要分词的字段设置了
fielddata
,就可以使用该字段进行聚合,
排序等。我们设置为
true
之后,在索引期间,就会以列式存储在内存中。为什
么存在于内存呢,因为按照
term
聚合,需要执行更加复杂的算法和操作,如果
基于磁盘或者
OS
缓存,性能会比较差。
fielddata
堆内存要求很高,如果数据量太大,对于
JVM
来及回收来说存在
一定的挑战,也就是对
ES
带来巨大的压力。所以
doc_value
的出现我们可以使用
磁盘存储,他同样是和
fielddata
一样的数据结构,在倒排索引基础上反向出来
的正排索引,并且是预先构建,即在建倒排索引的时候,就会创建
doc values
。
,
这会消耗额外的存储空间,但是对于
JVM
的内存需求就会减少。总体来看,
DocValues
只是比
fielddata
慢一点,大概
10-25%
,则带来了更多的稳定性。 cardlinality 聚集可以统计字段中不重复词项的数量,而
terms
聚集则可以将 这些词项全部展示出来。与 cardlinality
聚集一样,
terms
聚集统计出来的词频也
不能保证完全精确。例如
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"country_terms": {
"terms":{
"field": "DestCountry",
"size": 10
}
},
"country_terms_count":{
"cardinality": {
"field": "DestCountry"
}
}
}
}
在示例中定义了两个聚集,由于它们都是定义在
aggs
下,所以不是嵌套聚 集。terms
聚集的
field
参数定义了提取词项的字段为
DestCountry,
它的词项在 返回结果中会按词频由高到低依次展示,词频会在返回结果的 doc_count
字段中 展示。另一个参数 size
则指定了只返回
10
个词项,这相当把
DestCountry
字段 中词频前 10
名检索出来。
23、significant_terms
聚集
terms
聚集统计在字段中的词项及其词频,聚集结果会按各词项总的词频排 序,并讲现次数最多的词项排在最前面,这非常适合做推荐及热词类的应用。但 按词频总数不一定可能是总是正确的选择,在一些检索条件已知的情况下,一些
词频总数比较低的词项反而是更合适的推荐热词。 举例来说,假设在 10000
篇技术类文章的内容中提到
Elasticsearch
有
200
篇, 占比为 2%
;但在文章标题含有
NoSQL
的
1000
篇文章中,文章内容提到 Elasticsearch 的为
180
篇,占比为
18%
。 这种占比显著的提升,说明在文章标题 含有 NoSQL
的条件下,
Elasticsearch
变得更为重要。换句话说,如果一个词项在
某个文档子集中与在文档全集中相比发生了非常显著的变化,就说明这个词项在 这个文档子集中是更为重要的词项。
significant_terms
聚集就是针对上述情况的一种聚集查询,它将文档和词项 分为前景集 Foreground Set
和背景集
(Background Set)
。前景集对应一个文档子集, 面背景集则对应文档全集。significant_terms
聚集根据
query
指定前景集,运算 field 参数指定字段中的词项在前景集和背景集中的词频总数,并在结果的 doc_coumt 和
bg_coumt
中保存它们。例如
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"term":{
"OriginCountry": {"value": "IE"}
}
},
"aggs": {
"dest":{
"significant_terms": {
"field": "DestCountry"
}
}
}
}
在示例中,
query
参数使用
DSL
指定了前景集为出发国家为
IE (
即爱尔兰
)
的 航班,而聚集查询中则使用 significant_ terms
统计到达国家的前景集词频和背景 集词频。来看下返回结果:
在返回结果中,前景集文档数量为
119
,背景集文档数量为
13059
。 在 buckets
返回的所有词项中,国家编码为
GB
的航班排在第一位。它在前 景集中的词频为 12,
占比约为
10% (12/119);
而在背景集中的词频为
449
,占比约 为 3. 4% (445/13059)
。 词项 GB
在前景集中的占比是背景集中的
3
倍左右,发生了显著变化,所以 在这个前景集中 GB
可以被视为热词而排在第一位。
GB
代表的国家是英国,从爱 尔兰出发去英国的航班比较多想来也是合情合理的。 除了按示例方式使用 quey
参数指定前景集以外,还可以将
terms
聚集与 significant_terms 聚集结合起来使用,这样可以一次性列出一个字段的所有前景 集的热词。例如:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"orgin_dest":{
"terms":
{
"field": "OriginCountry"
},
"aggs": {
"dest":{
"significant_terms": {
"field": "DestCountry"
}
}
}
}
}
}
在示例中,使用
terms
聚集将
OriginCountry
字段的词项全部查询出来做前景 集,然后再与 significant_terms
聚集起查询它们的热词。
24、significant_text
聚集
如果参与
significant_terms
聚集的字段为
text
类型,那么需要将字段的 fielddata 机制开启,否则在执行时会返回异常信息。
significant_text
聚集与 significant_terms 聚集的作用类型,但不需要开启字段的
fielddata
机制,所以可 以把它当成是种专门为 text
类型字段设计的
significant_terms
聚集。例如在 kibana_sample_data_logs 中,
message
字段即为
text
类型,如果想在这个字段 上做词项分析就需要使用 significant_terms
聚集
:
POST /kibana_sample_data_logs/_search?filter_path=aggregations
{
"query": {
"term":{
"response": {
"value": "200"
}
}
},
"aggs": {
"agent_term":{
"significant_text":{
"field": "message"
}
}
}
}
在示例中,前景集为响应状态码
response
为
200
的日志,
significant_text
聚 集则查看在这个前景集下 message
字段中出现异常热度的词项。返回结果片段
:
通过展示的返回结果可以看出,排在第一位的词项
200
在前景集和背景集中 的数量是一样的, 这说明 message
中完整地记录了
200
状态码;而排在第二位 的词项 beats
前景集和背景集分别为
3462
和
3732
。这说明请求“
/beats"
地址的 成功率要远高于其他地址。 significant_text 聚集之所以不需要开启fielddata
机制是因为它会在检索时对 text 字段重新做分析,所以
significant_text
聚集在执行时速度比其他聚集要慢很 多。如果希望提升执行效率,则可以使用 sampler
聚集通过减少前景集的样本数 量降低运算量。
25、样本聚集
sampler
聚集的作用是限定其内部嵌套聚集在运算时采用的样本数量。
sampler
提取样本时会按文档检索的相似度排序,按相似度分值由高到低的顺序 提取。例如:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"term":{
"OriginCountry": {
"value": "IE"
}
}
},
"aggs": {
"sample_data": {
"sampler": {
"shard_size": 100
},
"aggs": {
"dest_country": {
"significant_terms": {
"field": "DestCountry"
}
}
}
}
}
}
在示例中共定义了
sample_ data
和
dest_country
两个聚集,其中 dest_country 是
sample_data
聚集的子聚集或嵌套聚集,因此
dest_country
在运 算时就只从分片上取一部分样本做运算。sampler
聚集的
shard_size
就是定义了 每个分片上提取样本的数量,这些样本会根据 DSL
查询结果的相似度得分由高到 低的顺序提取。 执行后会发现,这次目的地最热的目的地国家由 GB
变成了
KR,
这就是样本 范围缩小导致的数据失真。为了降低样本减少对结果准确性的影响,需要将些重 复的数据从样本中剔除。换句话说就是样本更加分散,加大样本数据的多样性。 Elasticsearch 提供的
diversified_sampler
聚集提供了样本多样性的能力,它提供了 field 或
script
两个参数用于去除样本中可能重复的数据。由于相同航班的票价可 能是相同的,所以可以将票价相同的航班从样本中剔除以加大样本的多样性,例 如:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"term":{
"OriginCountry": {
"value": "IE"
}
}
},
"aggs": {
"sample_data": {
"diversified_sampler": {
"shard_size": 100,
"field":"AvgTicketPrice"
},
"aggs": {
"dest_country": {
"significant_terms": {
"field": "DestCountry"
}
}
}
}
}
}
diversified_sampler
通过
field
参数设置了
AvgTicketPrice
字段,这样在返回结 果中 GB
就又重新回到了第一位。
26、单桶聚集
前面介绍的桶型聚集都是多桶型聚集,本节主要介绍单桶聚集 单桶聚集在返回结果中只会形成一个桶,它们都有比较特定的应用场最。在 Elasticsearch 中,单桶聚集主要包括
filter
,
global
,
missing
等几种类型。另外 还有一种 filters
聚集,它虽然属于多桶聚集, 但与
filter
聚集很接近,所以放到 一起说明。
27、过滤器聚集
过滤器聚集通过定义一个或多个过滤器来区分桶,满足过速器条件的文档将 落入这个过滤器形成的桶中。过滤器聚集分为单桶和多桶两种,对应的聚集类型 自然就是 filter
和
filters
。 本来看 filter
桶型聚集,它属于单桶型聚集。一般会同时嵌套一个指标聚集, 用于在过滤后的文档范围内计算指标,例如:
POST /kibana_sample_data_flights/_search?size=0&filter_path=aggregations
{
"aggs" : {
"origin_cn": {
"filter": {
"term": {
"OriginCountry":"CN"
}
},
"aggs": {
"cn_ticket_price": {
"avg": {
"field": "AvgTicketPrice"
}
}
}
},
"avg_price": {
"avg": {
"field": "AvgTicketPrice"
}
}
}
}
在示例中一共定义了
3
个聚集,最外层是两个聚集,最后聚集为嵌套聚集, origin_cn 聚集为单过滤器的桶型聚集,它将所有
OriginCountry
为
CN
的文档归入 一桶。origin_cn 桶型聚集嵌套了
cn_ticket_price
指标聚集, 它的作用是计算当前 桶内文档 AvgTicketPrice
字段的平均值。另一个外层聚集
avg_price
虽然也是计 算 AghckePie
字段的平均值,但它计算的是所有文档的平均值。实际上,使用
query 与 agg
结合起来也能实现类似的功能,区别在于过滤器不会做相似度计算,所以 效率更高一些也更灵活一些。 多过滤器与单过滤器的作用类似,只是包含有多个过滤器,所以会形成多个 桶。多过滤博型聚集使用 filters 参数接收过滤条件的数组,一般也是与指标聚集 一同使用。例如使用两个过滤器计算从中国、美国出发的航班平均机票价格:
POST /kibana_sample_data_flights/_search?size=0&filter_path=aggregations
{
"aggs" :{
"origin_cn_us":{
"filters": {
"filters":[
{
"term": {
"OriginCountry": "CN"
}
},
{
"term": {
"OriginCountry": "US "
}
}
]
},
"aggs":{
"avg_ price":{
"avg": {
"field": "AvgTicketPrice"
}
}
}
}
}
}
28、global
聚集
global
桶型聚集也是一种单桶型聚集, 它的作用是把索引中所有文档归入 一个桶中。这种桶型聚集看似没有什么价值,但当 global
桶型聚集与
query
结 合起来使用时,它不会受 query
定义的查询条件影响,最终形成的桶中仍然包含 所有文档。global
聚集在使用上非常简单,没有任何参数,例如
:
POST /kibana_sample_data_flights/_search?size=0&filter_path=aggregations
{
"query": {
"term":{
"Carrier": {
"value": "Kibana Airlines"
}
}
},
"aggs":{
"kibana_avg_delay": {
"avg": {
"field": "FlightDelayMin"
}
},
"all flights": {
"global": {},
"aggs": {
"all_avg_delay": {
"avg": {
"field": "FlightDelayMin"
}
}
}
}
}
}
在示例中
query
使用
term
查询将航空公司为“
Kibana Airline"
的文档都检索 出来,而 kibana _avg delay
定义的平均值聚集会将它们延误时间的平均值计算出 来。但另个 all_fights
聚集由于使用了
global
聚集所以在嵌套的
all_avg_delay
聚 集中计算出来的是所有航班廷误时间的平均值。
29、missing
聚集
missing
聚集同样也是一种单桶型聚集,它的作用是将某一字段缺失的文档 归入一桶。
missing
聚集使用
field
参数定义要检查缺失的字段名称,例如
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"no_price": {
"missing": {
"field": "AvgTicketPrice"
}
}
}
}
示例将
kibana_sample_data_flights
中缺失
AvgTicketPrice
字段的文档归入一 桶,通过返回结果的 doc_count
查询数量也可以与指标聚集做嵌套,计算这些文 档的某一指标值。
30、聚集组合
有两种比较特殊的多桶型聚集,它们是
composite
聚集和
adjacency_matrix 聚集。这两种聚集是以组合不同条件的形式形成新桶,只是在组合的方法和组件 的条件上存在着明显差异。 composite 聚集可以将不同类型的聚集组合到一一起,它会从不同的聚集中 提取数据,并以笛卡尔乘积的形式组合它们,而每一个组合就会形成一个新桶。 例如想查看平均票价与机场天气的对应关系,可以这样:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs" :{
"price_weather" : {
"composite" : {
"sources":[
{"avg_price": {"histogram":{"field": "AvgTicketPrice",
"interval":500}}},
{"weather":{"terms": {"field": "OriginWeather"}}}
]
}
}
}
}
在示例中,
composite
聚集中通过
soures
参数定义了两个需要组合的子聚集。
第一个聚集
avg_price
是一个针对
AvgTicketPrice
以
500
为间隔的
histogam
聚集,
第二个则聚集
weather
则一个针对
OriginWeather
的
terms
聚集。
sources
参数 中还可以定义更多的聚集,它们会以笛卡儿乘积的形式组合起来。 在返回结果中除了由各聚集组合形成的桶以外,还有一个 after_key
字段,
它包含自前聚集结果中最后一个结果的
key
。所以请求下一页聚集结果就可 以通过 after
和
size
参数值定,例如
:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs" :{
"price_weather" : {
"composite" : {
"after":{
"avg_price":500.0,
"weather":"Cloudy"
},
"sources":[
{"avg_price": {"histogram":{"field": "AvgTicketPrice",
"interval":500}}},
{"weather":{"terms": {"field": "OriginWeather"}}}
]
}
}
}
}
adjacency_matrix
又叫邻接矩阵,是图论中的概念,描述顶点之间的相邻关 系,adjacency_matrix
聚集因为牵涉到这些概念,略过,感兴趣的同学可以自行 研究。
ELK聚集查询之指标聚集和单通聚集到此分析完毕,下篇分析ELK聚集查询之管道聚集和SQL语言,敬请期待。