桶聚合:Bucket Aggregations
概念
类比SQL中的groupBy的作用,主要用于统计不同类型数据的数量。
在Elasticsearch中,桶聚合是一种常用的聚合查询操作,它将文档分为多个“桶”,然后在每个桶上进行统计分析。
场景
桶聚合可以用于各种场景,例如: 对数据进行分组统计,比如按照地区、年龄段、性别等字段进行分组统计。
三种类型的聚合
桶聚合:Bucket Aggregations
概念
类比SQL中的groupBy的作用,主要用于统计不同类型数据的数量。
在Elasticsearch中,桶聚合是一种常用的聚合查询操作,它将文档分为多个“桶”,然后在每个桶上进行统计分析。
场景
桶聚合可以用于各种场景,例如: 对数据进行分组统计,比如按照地区、年龄段、性别等字段进行分组统计。
对时间序列数据进行时间段分析,比如按照每小时、每天、每月、每季度、每年等时间段进行分析。
对各种标签信息分类,并统计其数量。
用法
以orders订单索引为例
还包含了一个代码示例,具体是:
GET orders/_search
{
"aggs": {
"agg_tag_value_count": { //自定义名称,规范要求看名知其意
"terms": {
"field": "tags.keyword" // 注意如果是文本,请使用keyword类型
}
}
}
}
例如:
统计不同总价区间之间的订单数据量
GET orders/_search
{
"aggs": {
"range_total_price": { //自定义名称,规范要求看名知其意
"range":{
"field": "total_price",
"ranges": [
{
//总价在1000-1100之间的订单数据
"from": 1000,
"to":1100
},
{
//总价在1100-1200之间的订单数据
"from": 1100,
"to":1200
},
{
//总价在2000之间的订单数据
"from":2000
}
]
}
}
}
}
Multi_terms
当在聚合的时候需要对多个字段同时聚合的时候,可以使用multi_terms来完成
GET /<index_name>/_search
{
"aggs": {
"agg_name": {
"multi_terms": {
"terms": [
{
"field": "field_1"
},
{
"field": "field_2"
}
]
}
}
}
}
示例:
根据订单商品的品牌和标签统计
GET orders/_search
{
"aggs": {
"band_tags": {
"multi_terms": {
"terms": [
{
"field": "Brand"
},
{
"field": "tags.keyword"
}
]
}
}
}
}
指标聚合:Metrics Aggregations
场景
用于统计某个指标,如最大值、最小值、平均值,可以结合桶聚合一起使用,如按照商品类型分桶,统计每个桶的平均价格。
品牌 | 商品类型的订单总价的平均值 | 订单商品分类的平均值 |
---|---|---|
指标函数
平均值: Avg
最大值: Max
最小值: Min
求和: Sum
详细信息: Stats
数量: Value count
示例:
GET orders/_search
{
"aggs": {
"total_price_max": {
"max":{
"field": "total_price"
}
},
"total_price_min": {
"min":{
"field": "total_price"
}
}
,
"total_price_avg": {
"avg":{
"field": "total_price"
}
}
}
}
GET orders/_search
{
"aggs": {
"total_price_stats": {
"stats":{
"field": "total_price"
}
}
}
}
管道聚合:Pipeline Aggregations
概念
管道聚合用于对聚合的结果进行二次聚合,如要统计绑定数量最多的标签 bucket,就是要先按照标签进行分桶,再在分桶的结果上计算最大值。
场景
用于对聚合查询的二次聚合,如统计订单各商品品牌商品平均价格,即先按照订单商品品牌进行桶聚合,并计算其平均总价,然后对总价计算最大值聚合
语法
GET <index_name>/_search
{
"aggs": {
"my_aggs": {
"<function>": {
...
}
},
"aggs": {
"my_price_bucket": {
...
}
}
},
"my_min_bucket": {
"<pip_function>": {
"buckets_path": "my_aggs>price_bucket"
}
}
}
示例:
统计订单各商品品牌商品平均价格,即先按照订单商品品牌进行桶聚合,并计算其平均总价,然后对总价计算最大值聚合和最小值聚合
GET orders/_search
{
"aggs": {
"agg_pip_total_price": {
"terms": {
"field": "Brand"
},
"aggs": {
"avg_total_price": {
"avg": {
"field": "total_price"
}
}
}
},
"min_avg_total_price": {
"min_bucket": {
"buckets_path": "agg_pip_total_price>avg_total_price"
}
},
"max_avg_total_price": {
"max_bucket": {
"buckets_path": "agg_pip_total_price>avg_total_price"
}
}
}
}
聚合数据类型
doc values
doc values是正排索引的基本数据结构之一,其存在是为了提升排序和聚合效率,默认true,如果确定不需要对字段进行排序或聚合,也不需要通过脚本访问字段值,则可以禁用doc values值以节省磁盘空间。
从广义来说,doc values本质上是一个序列化的列式存储。列式存储适用于聚合、排序、脚本等操作,所有的数字、地理坐标、日期、IP和不分词(not_analyzed)字符类型都会默认开启,不支持text和annotated_text类型
PUT sample_doc_values
{
"mappings": {
"properties": {
"detail_text": {
"type": "text"
}
}
}
}
//错误示例:如上所说,text类型不支持排序和聚合
GET sample_doc_values/_search
{
"sort":[
{
"detail_text": {
"order":"desc"
}
}
]
}
//解决方式:创建一个子字段 类型keyword
delete sample_doc_values
PUT sample_doc_values
{
"mappings": {
"properties": {
"detail_text": {
"type": "text",
"fields":{
"doc_values_detail":{
"type":"keyword",
"doc_values":true
}
}
}
}
}
}
//利用detail_text的子字段doc_values_detail排序
GET sample_doc_values/_search
{
"sort":[
{
"detail_text.doc_values_detail": {
"order":"desc"
}
}
]
}
fielddata
概念:查询时内存数据结构,在首次用当前字段聚合、排序或者在脚本中使用时,需要字段为fielddata数据结构,并且创建倒排索引保存到堆中。与doc value不同,当没有doc value的字段需要聚合时,需要打开fielddata,然后临时在内存中建立正排索引,fielddata的构建和管理发生在JVM Heap中。Fielddata默认是不启用的,因为text字段比较长,一般只做关键字分词和搜索,很少拿它来进行全文匹配和聚合还有排序。
PUT sample_doc_values
{
"mappings": {
"properties": {
"detail_text": {
"type": "text",
"fields":{
"doc_values_detail":{
"type":"keyword",
"fielddata":true
}
}
}
}
}
}
//利用detail_text的子字段doc_values_detail进行聚合
GET sample_doc_values/_search
{
"aggs":{
"sample":{
"terms":{
"field": "detail_text.doc_values_detail"
}
}
}
}