ELK聚集查询之指标聚集和单通聚集(八)

这篇分析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语言,敬请期待。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值