当前位置: 代码迷 >> 综合 >> Elasticsearch7.x DSL语法之聚合查询
  详细解决方案

Elasticsearch7.x DSL语法之聚合查询

热度:81   发布时间:2023-12-03 19:29:49.0

程序员小强总结的 ElasticSearch专题超全总结篇在这里:传送门
结合官网资料,做了更详细的实际使用总结。
从单机版安装到集群高可用生产环境搭建、基本概念(索引,分片,节点,倒排索引…)、DSL语法实践、分词器(内置+中文)、SpringBoot整合实战、仿京东商品搜索实战实现。

1.前言

聚合查询是开发中常见的场景,一般包含。求和、最大值、最小值、平均值、总记录数等。

注意事项:text类型是不支持聚合的。

1.1.初始测试数据

学习SQL中常用的案例,老师信息表
字段信息:name(姓名) | age(年龄) | job(工作岗位) | sex(性别1-男,2-女) | salary(薪资)

#老师信息
#注:每个岗位都是神圣的,以下测试数据,纯属虚构,仅测试需要
PUT /teacher_info/_bulk
{
     "index" : {
      "_id" : "101" } }
{
     "name" : "Tom","age":32,"job":"Math","sex":1,"salary": 3000 }
{
     "index" : {
      "_id" : "102" } }
{
     "name" : "Zhangsan","age":22,"job":"Java","sex":1,"salary": 5000}
{
     "index" : {
      "_id" : "103" } }
{
     "name" : "lisi","age":29,"job":"sports","sex":1,"salary": 4000 }
{
     "index" : {
      "_id" : "104" } }
{
     "name" : "wangwu","age":25,"job":"sports","sex":1,"salary": 4300}
{
     "index" : {
      "_id" : "105" } }
{
     "name" : "Mary","age":30,"job":"H5","sex":2,"salary": 4800}
{
     "index" : {
      "_id" : "106" } }
{
     "name" : "Luccy","age":33,"job":"English","sex":2,"salary": 5500 }
{
     "index" : {
      "_id" : "107" } }
{
     "name" : "Xiaomei","age":23,"job":"English","sex":2,"salary": 5800 }
{
     "index" : {
      "_id" : "108" } }
{
     "name" : "Xiaogao","age":27,"job":"Php","sex":1,"salary": 3900}
{
     "index" : {
      "_id" : "109" } }
{
     "name" : "Dabai","age":26,"job":"Chinese","sex":1,"salary": 4000 }
{
     "index" : {
      "_id" : "110" } }
{
     "name" : "Xiaowei","age":25,"job":"C++","sex":1,"salary": 4500 }

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

在查询请求体中以aggregations节点语法如下:**

"aggregations" : {
    "<aggregation_name>" : {
                                     <!--聚合的名字 -->"<aggregation_type>" : {
                                 <!--聚合的类型 --><aggregation_body>                               <!--聚合体:对哪些字段进行聚合 -->}[,"meta" : {
      [<meta_data_body>] } ]?                <!--元 -->[,"aggregations" : {
     [<sub_aggregation>]+ } ]?       <!--在聚合里面在定义子聚合 -->}
}

注:aggregations 也可简写为 aggs

2.求和(Sum)

案例:求所有老师的薪资总和
注:“size”: 0 ,参数表示不用返回文档列表,只返回汇总的数据即可

GET teacher_info/_search
{
    "size": 0,"aggs": {
    "sum_salary": {
    "sum": {
    "field":"salary"}}}
}

在这里插入图片描述

3.最大值(Max)

示例:求薪资最大值

GET teacher_info/_search
{
    "size": 0,"aggs": {
    "max_salary": {
    "max": {
    "field":"salary"}}}
}

4.最小值(Min)

案例:求薪资最低值

GET teacher_info/_search
{
    "size": 0,"aggs": {
    "min_salary": {
    "min": {
    "field":"salary"}}}
}

5.平均值(Avg)

案例:求薪资平均值

GET teacher_info/_search
{
    "size": 0,"aggs": {
    "avg_salary": {
    "avg": {
    "field":"salary"}}}
}

6.去重数值(cardinality)

类似mysql的 count distinct
案例:老师一共教了多少学科

GET teacher_info/_search
{
    "size": 0,"aggs" : {
    "job_count" : {
    "cardinality" : {
    "field" : "job.keyword"}}}
}

由于在创建索引的时候,没有先创建Mapping, job这个字段默认是 text类型,而聚合统计不知道text类型,
所以这里需要使用“job.keyword”
在这里插入图片描述

字符串类型的参数,在没有指定mapping的情况下,默认生成的类型如上图。
在这里插入图片描述

7.多值查询-最大最小和平均值

案例:查询最低、最高和平均工资

GET teacher_info/_search
{
    "size": 0,"aggs": {
    "max_salary": {
    "max": {
    "field": "salary"}},"min_salary": {
    "min": {
    "field": "salary"}},"avg_salary": {
    "avg": {
    "field": "salary"}}}
}

在这里插入图片描述

8.返回多个聚合值(Status)

stats 统计,请求后会直接显示多种聚合结果,总记录数,最大值,最小值,平均值,汇总值

GET employees_info/_search
{
    "size": 0,"aggs": {
    "salary_stats": {
    "stats": {
    "field":"salary"}}}
}

在这里插入图片描述

9.百分比(Percentiles)

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

GET teacher_info/_search
{
    "size": 0,"aggs": {
    "age_percentiles": {
    "percentiles": {
    "field": "age"}}}
}

默认按照[ 1, 5, 25, 50, 75, 95, 99 ]来统计
在这里插入图片描述

返回结果可以理解为:占比为25%的文档的age值 <= 25,或反过来:age<=25的文档数占总命中文档数的25%
因为是默认返回的 ,[ 1, 5, 25, 50, 75, 95, 99 ] 所以 可能存在重复值

key-value形式返回
添加参数"keyed": false
在这里插入图片描述

10.文档值占比(Percentile Ranks)

这里指定值,查占比。注意占比是小于文档值的比例

GET teacher_info/_search
{
    "size": 0,"aggs" : {
    "age_percentiles" : {
    "percentile_ranks" : {
    "field" : "age", "values" : [ 22, 25, 33]}}}
}

下图含义

  • 小于age<=22的占比 5%
  • 小于age<=25的占比 30%
  • 小于age<=33的占比 100%
    在这里插入图片描述

11.中位数查询

案例:求工资中位数

POST teacher_info/_search
{
    "size": 0,"aggs": {
    "load_time_outlier": {
    "percentiles": {
    "field": "salary","percents" : [ 50, 99],"keyed": false}}}
}

在这里插入图片描述

12.分组取Top N 之(Top Hits)

案例1:根据性别分组。展示工资排名top3

GET /teacher_info/_search?size=0
{
    "aggs": {
    "top_tags": {
    "terms": {
    "field": "sex"},"aggs": {
    "top_sales_hits": {
    "top_hits": {
    "sort": [{
    "salary": {
    "order": "desc"}}],"_source": {
    "includes": [ "name", "sex","salary" ]},"size" : 3}}}}}
}

在这里插入图片描述

13.分组之聚合

案例:根据性别分组求平均工资

GET /teacher_info/_search
{
    "size":0,"aggs": {
    "top_tags": {
    "terms": {
    "field": "sex"},"aggs": {
    "avg_salary": {
    "avg": {
    "field": "salary"}}}}}
}

14.总记录数查询

类似mysql的count

#方式1:统计年龄 >=25 的记录数
GET teacher_info/_count
{
    "query": {
    "range": {
    "age":{
    "gte": 25}}}
}#方式2:统计年龄 >=25 的记录数
GET teacher_info/_search?size=0
{
    "query": {
    "range": {
    "age":{
    "gte": 25}}}
}

在这里插入图片描述

附录

官方示例:传送门