elasticsearch聚合查询

聚合查询


  1. 聚合(aggs)不同于普通查询,是目前学到的第二种大的查询分类,第一种即“query”,因此在代码中的第一层嵌套由“query”变为了“aggs”。用于进行聚合的字段必须是exact value,分词字段不可进行聚合,对于text字段如果需要使用聚合,需要开启fielddata,但是通常不建议,因为fielddata是将聚合使用的数据结构由磁盘(doc_values)变为了堆内存(field_data),大数据的聚合操作很容易导致OOM,详细原理会在进阶篇中阐述。

概念

聚合分类

    1. 分桶聚合(Bucket agregations):类比SQL中的group by的作用,主要用于统计不同类型数据的数量
    2. 指标聚合(Metrics agregations):主要用于最大值、最小值、平均值、字段之和等指标的统计
    3. 管道聚合(Pipeline agregations):用于对聚合的结果进行二次聚合,如要统计绑定数量最多的标签bucket,就是要先按照标签进行分桶,再在分桶的结果上计算最大值。

语法

GET product/_search
{
  "aggs": {
    "<aggs_name>": {
      "<agg_type>": {
        "field": "<field_name>"
      }
    }
  }
}


aggs_name:聚合函数的名称
agg_type:聚合种类,比如是桶聚合(terms)或者是指标聚合(avg、sum、min、max等)
field_name:字段名称或者叫域名。


  1. 场景:用于统计不同种类的文档的数量,可进行嵌套统计。
    函数:terms
    注意:聚合字段必须是exact value,如keyword

桶聚合:


  1. 场景:用于统计某个指标,如最大值、最小值、平均值,可以结合桶聚合一起使用,如按照商品类型分桶,统计每个桶的平均价格。
    函数:平均值:Avg、最大值:Max、最小值:Min、求和:Sum、详细信息:Stats、数量:Value count
GET product/_search
{
  "size": 0, 
  "aggs": {
    "aggs_tag": {
      "terms": {
        "field": "tags.keyword",
        "size": 5,
        "order": {
          "_count": "asc"
        }
      }
    }
  }
}

指标聚合


  1. 场景:用于对聚合查询的二次聚合,如统计平均价格最低的商品分类,即先按照商品分类进行桶聚合,并计算其平均价格,然后对其平均价格计算最小值聚合
    函数:Min bucket:最小桶、Max bucket:最大桶、Avg bucket:桶平均值、Sum bucket:桶求和、Stats bucket:桶信息
    注意:buckets_path为管道聚合的关键字,其值从当前聚合统计的聚合函数开始计算为第一级。比如下面例子中,my_aggs和my_min_bucket同级, my_aggs就是buckets_path值的起始值。
GET product/_search
{
  "size": 0,
  "aggs": {
    "max_price": {
      "max": {
        "field": "price"
      }
    },
    "min_price": {
      "min": {
        "field": "price"
      }
    },
    "avg_price":{
      "avg": {
        "field": "price"
      }
    },
    "count_price":{
      "value_count": {
        "field": "price"
      }
    }
  }
}

管道聚合

GET product/_search
{
  "size": 0, 
  "aggs": {
    "my_aggs": {
      "terms": {
        ...
      },
      "aggs": {
        "my_price_bucket": {
          ...
        }
      }
    },
    "my_min_bucket":{
      "min_bucket": {
        "buckets_path": "my_aggs>price_bucket"
      }
    }
  }
}


  1. 语法:

嵌套聚合

GET product/_search
{
  "size": 0,
  "aggs": {
    "<agg_name>": {
      "<agg_type>": {
        "field": "<field_name>"
      },
      "aggs": {
        "<agg_name_child>": {
          "<agg_type>": {
            "field": "<field_name>"
          }
        }
      }
    }
  }
}


用途:用于在某种聚合的计算结果之上再次聚合,如统计不同类型商品的平均价格,就是在按照商品类型桶聚合之后,在其结果之上计算平均价格

GET product/_search
{
  "size": 0,
  "aggs": {
    "type_term": {
      "terms": {
        "field": "type.keyword"
      },
      "aggs": {
        "avg_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    },
    "min_bucket_type":{
      "min_bucket": {
        "buckets_path": "type_term>avg_price"
      }
    }
  }
}

聚合和查询的相互关系


    1. 语法:
基于query或filter的聚合
GET product/_search
{
  "query": {
    ...
  }, 
  "aggs": {
    ...
  }
}
GET product/_search
{
  "size": 2, 
  "query": {
    "range": {
      "price": {
        "gte": 4000
      }
    }
  }, 
  "aggs": {
    "tags_agg": {
      "terms": {
        "field": "tags.keyword"
      }
    }
  }
}


注意:以上语法,执行顺序为先query后aggs,顺序和谁在上谁在下没有关系。query中可以是查询、也可以是filter、或者bool query

基于聚合结果的查询、
GET product/_search
{
  "aggs": {
    ...
  },
  "post_filter": {
    ...
  }
}


注意:以上语法,执行顺序为先aggs后post_filter,顺序和谁在上谁在下没有关系。

查询条件的作用域
GET product/_search
{
  "size": 10,
  "query": {
    ...
  },
  "aggs": {
    "avg_price": {
      ...
    },
    "all_avg_price": {
      "global": {},
      "aggs": {
        ...
      }
    }
  }
}


上面例子中,avg_price的计算结果是基于query的查询结果的,而all_avg_price的聚合是基于all data的

聚合排序


    1. order_type:count(数量) key(聚合结果的key值) _term(废弃但是仍然可用,使用_key代替)
排序规则:
GET product/_search
{
  "aggs": {
    "type_agg": {
      "terms": {
        "field": "tags",
        "order": {
          "<order_type>": "desc"
        },
        "size": 10
      }
    }
  }
}

多级排序:即排序的优先级,按照外层优先的顺序
GET product/_search?size=0
{
  "aggs": {
    "first_sort": {
      ...
      "aggs": {
        "second_sort": {
          ...
        }
      }
    }
  }
}


上例中,先按照first_sort排序,再按照second_sort排序

多层排序:即按照多层聚合中的里层某个聚合的结果进行排序
GET product/_search
{
  "size": 0,
  "aggs": {
    "tag_avg_price": {
      "terms": {
        "field": "type.keyword",
        "order": {
          "agg_stats>my_stats.sum": "desc"
        }
      },
      "aggs": {
        "agg_stats": {
         	...
          "aggs": {
            "my_stats": {
              "extended_stats": {
                ...
              }
            }
          }
        }
      }
    }
  }
}


上例中,按照里层聚合“my_stats”进行排序

常用的查询函数


    1. 用途:用于区间统计,如不同价格商品区间的销售情况
      语法:
histogram:直方图或柱状图统计
GET product/_search?size=0
{
  "aggs": {
    "<histogram_name>": {
      "histogram": {
        "field": "price", 				#字段名称
        "interval": 1000,					#区间间隔
        "keyed": true,						#返回数据的结构化类型
        "min_doc_count": <num>,		#返回桶的最小文档数阈值,即文档数小于num的桶不会被输出
        "missing": 1999						#空值的替换值,即如果文档对应字段的值为空,则默认输出1999(参数值)
      }
    }
  }
}
GET product/_search?size=0
{
  "aggs": {
    "price_histogram": {
      "histogram": {
        "field": "price",
        "interval": 1000,
        "min_doc_count": 1
      }
    }
  }
}


    1. 语法:
date-histogram:基于日期的直方图,比如统计一年每个月的销售额
GET product/_search?size=0
{
  "aggs": {
    "my_date_histogram": {
      "date_histogram": {
        "field": "createtime",					#字段需为date类型
        "<interval_type>": "month",			#时间间隔的参数可选项
        "format": "yyyy-MM", 						#日期的格式化输出
        "extended_bounds": {						#输出空桶
          "min": "2020-01",
          "max": "2020-12"
        }
      }
    }
  }
}
GET product/_search?size=0
{
  "aggs": {
    "date": {
      "date_histogram": {
        "field": "createtime",
        "interval": "month",
        "format": "yyyy-MM",
        "extended_bounds": {
          "min": "2020-01",
          "max": "2020-12"
        }
      },
      "aggs": {
        "sum": {
          "sum": {
            "field": "price"
          }
        },
        "my_cumulative_sum": {
          "cumulative_sum": {
            "buckets_path": "sum"
          }
        }
      }
    }
  }
}


interval_type:时间间隔的参数可选项
fixed_interval:ms(毫秒)、s(秒)、 m(分钟)、h(小时)、d(天),注意单位需要带上具体的数值,如2d为两天。需要当心当单位过小,会 导致输出桶过多而导致服务崩溃。
calendar_interval:month、year
interval:(废弃,但是仍然可用)


    1. 计算结果为何为近似值
percentile 百分位统计 或者 饼状图
      1. percentiles:用于评估当前数值分布情况,比如99 percentile 是 1000 , 是指 99%的数值都在1000以内。常见的一个场景就是我们制定 SLA 的时候常说 99% 的请求延迟都在100ms 以内,这个时候你就可以用 99 percentile 来查一下,看一下 99 percenttile 的值如果在 100ms 以内,就代表SLA达标了。
        语法:
GET product/_search?size=0
{
  "aggs": {
    "<percentiles_name>": {
      "percentiles": {
        "field": "price",
        "percents": [
  				percent1,				#区间的数值,如5、10、30、50、99 即代表5%、10%、30%、50%、99%的数值分布
  				percent2,
  				...
        ]
      }
    }
  }
}
GET product/_search?size=0
{
  "aggs": {
    "price_percentiles": {
      "percentiles": {
        "field": "price",
        "percents": [
          1,
          5,
          25,
          50,
          75,
          95,
          99
        ]
      }
    }
  }
}

      1. percentile_ranks: percentile rank 其实就是percentiles的反向查询,比如我想看一下 1000、3000 在当前数值中处于哪一个范围内,你查一下它的 rank,发现是95,99,那么说明有95%的数值都在1000以内,99%的数值都在3000以内。
GET product/_search?size=0
{
  "aggs": {
    "<percentiles_name>": {
      "percentile_ranks": {
        "field": "<field_value>",
        "values": [
          rank1,
          rank2,
          ...
        ]
      }
    }
  }
}
GET product/_search?size=0
{
  "aggs": {
    "price_percentile_ranks": {
      "percentile_ranks": {
        "field": "price",
        "values": [
          1000,
          2000,
          3000,
          4000,
          5000,
          6000
        ]
      }
    }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值