《再也不怕elasticsearch》es聚合使用与原理剖析

2023-11-15

大家好我是迷途,一个在互联网行业,摸爬滚打的学子。热爱学习,热爱代码,热爱技术。热爱互联网的一切。再也不怕elasticsearch系列,帅途会慢慢由浅入深,为大家剖析一遍,各位大佬请放心,虽然这个系列帅途有时候更新的有点慢,但是绝对不会烂尾!如果你喜欢本系列的话,就快点赞关注收藏安排一波吧~

前言

本文主要讲解es中的聚合查询,一般来说在es中,复杂查询,我们不会使用太多,但是在一些特定的场景下,我们就可能需要使用到。例如我们在使用es做一个大型的日志分析系统的时候(ELK),那么我们对数据的一些统计聚合等都是需要我们进行操作的,工欲善其事必先利其器,所以今天帅途就和大家一起来学习es的聚合查询吧。
在这里插入图片描述

正文

1、聚合的一些基本概念
  • aggs关键字

    聚合关键字,优先级低,一个aggs里面可以有多个聚合,每个聚合是相互独立的,如果本次查询中有query无论确query位置在何处,我们聚合查询的都是query之后的参数

    例:查询出性别为女的数据,然后求他们年龄的平均值(query优先级高于aggs)

    {
        "aggs" : { "avg_grade" : {"avg" : { "field" : "age" }}},
        "query": {"term": { "gender": "女" }}
    }
    
  • ES的4种聚合
    在这里插入图片描述

    参考官方文档:elasticsearch官方文档

  • Bucketing

    桶,es的4种聚合类型之一,将满足同一种条件的数据放在一个桶中,类似于mysql中的sql中的group by 语句。与指标聚合不同,桶聚合可以包含子聚合,例如张三(数据)在地球(桶)中,同时他也属于地球之内的中国(子桶)中

  • Metric

    指标(度量),指标聚合,类似于sql中的avg、sum、max等,在metric中主要有两种聚合分别是单值聚合(single-value numeric)和多值聚合(multi-value numeric)。顾名思义,单值聚合就是在本次聚合中只有一个值而多值聚合则是在聚合中有多个值

  • Matrix

    矩阵,矩阵聚合,可以对多个字段进行聚合,生成数据矩阵。类似于分别使用Metric的多值聚合对数据进行聚合,目前矩阵聚合还处于测试阶段,可能后期会完全更改或者删除。并且不支持脚本

  • Pipeline

    管道,管道聚合,它作用于其他聚合的结果之上,主要分为两种聚合Parent(父母)、Sibling(兄弟),管道聚合支持链路但是不能在管道聚合中在写子聚合。
     
    Parent(父母):对父聚合处理后的数据进行处理,不会生成新的桶。在父聚合之内。
    Sibling(兄弟):同级聚合,对当前同一级的聚合数据进行处理,生成新桶,必须处于多聚合之内。

2、环境准备

PostMan、ES7.X、ElasticSearch-Head

3、数据准备

这里帅途已经预先添加好了数据,我们使用head查看,数据内容与格式。有些小伙伴可能不太了解head与kibana的区别,head与kibana都是es的数据可视化工具,在日常的开发当中,可以根据我们的需求进行选择,帅途一般索引管理等用head,数据查询之类使用kibana。

我们在customer索引下准备了10条数据,他们的类型为userType,各位小伙伴注意,在es7.0之后一个index只能对应一个type,在后面可能会完全弃用。

  • 准备数据
    在这里插入图片描述
4、Bucketing聚合
  • 根据性别进行分组

    http://112.74.48.31:9200/customer/_search?size=0										   	 ---GET
    {  
    	"aggs":{
    		"metoo_group":{   --自定义聚合名称
    			"terms":{     -- 匹配关键字
    				"field":"gender"    --gener字段
    			}
    		}
    	}
    }
    

    size=0表示我们对这个查询本身查询出来的数据不感兴趣,只查看聚合后的数据

    在我们执行上述代码之后,发现一个问题:Fielddata is disabled on text fields by default. Set fielddata=true on [gender] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.

    众所周知es底层是基于lucene,默认使用倒排索引,来提升我们的查询效率,而在我们对text字段进行聚排序(sort),统计(aggs)的时候,就需要使用到FieldData(正排索引),在es5.0之后这个默认为关闭状态,因为正排索引使用的是 doc values 将数据缓存在内存当中,典型的使用空间换时间,当我们内存不够时,os会为我们将数据写入到磁盘中,甚至在我们海量的情况下会出现OOM等异常。
     
    正排索引:将文档加载到内存(磁盘)中,从文档 Id 到文档内容、单词的关联关系,也就是说可以通过 Id获取到文档的内容。
    倒排索引:将文档内容进行分词,每个分词对应文档id,如果一个分词对应了多个文档id,则生成索引矩阵。

    帅途这里发现一篇非常有意思的文章,对倒排索引和正排索引不太理解的同学可以去看看,参考:终于有人把Elasticsearch原理讲透了!

    接下来我们手动修改index中gender字段的FieldData属性,开启正排索引,并进行分组查询。

    http://112.74.48.31:9200/customer/_mapping														-POST
    {
    	"properties":{
    		"gender":{   		-- 字段名称
    			"type":"text", 	-- 字段类型 修改报错
    			"fielddata":true	--开启正排索引
    		}
    	}
    }
    

    修改之后,我们再次调用聚合函数进行分组查询,查看返回值

    {
        "took": 46,
        "timed_out": false,
        "_shards": { -- 分片,不了解的同学可以去看帅途之前的博客
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "metoo_group": {		-- 我们自定义的桶名
                "doc_count_error_upper_bound": 0,   --被遗漏的terms 可能的最大值
                "sum_other_doc_count": 0,			--除了返回给用户的terms,剩下的terms总数
                "buckets": [
                    {
                        "key": "男",
                        "doc_count": 6
                    },
                    {
                        "key": "女",
                        "doc_count": 4
                    }
                ]
            }
        }
    }
    
  • 根据性别进行分组,分别求出平均年龄

    http://112.74.48.31:9200/customer/_search?size=0										   	 ---GET
    {
        "aggs":{
            "metoo_group":{
                "terms":{
                    "field":"gender"   
                },
                "aggs":{ 					--在metoo_group的基础之上创建子聚合,计算平均年龄
                    "sum_group":{			--自定义的聚合名称
                        "avg":{	--对age字段进行求平均数
                            "field":"age"   
                        }
                    }
                }
            }
        }
    }
    

    查看返回的聚合结果

    {
        "took": 3,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "metoo_group": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                    {
                        "key": "男",
                        "doc_count": 6,
                        "sum_group": {  -- 子聚合返回值
                            "value": 32.166666666666664
                        }
                    },
                    {
                        "key": "女",
                        "doc_count": 4,
                        "sum_group": {
                            "value": 26.75
                        }
                    }
                ]
            }
        }
    }
    
5、Metric聚合
  • 求所有人的总年龄(sum聚合)

    http://112.74.48.31:9200/customer/_search?size=0											-GET
    {
        "aggs" : {
            "metoo_sum": {
                    "sum": {      		--求和关键字
                        "field": "age"
                    }
            }
        }
    }
    

    返回值解析

    {
        "took": 14,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {  -- 索引的文档,由于我们设置的size=0,所以这里不展示
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": { -- 聚合桶返回值
            "metoo_sum": {	--我们自定义的桶名
                "value": 300.0 
            }
        }
    }
    

    单值聚合基本上都大同小异,帅途这里把格式列出来之后,一些常用的聚合参数直接替换即可,avg(平均)、sum(求和)、max*(最大值)、min(最小值)、cardinality(唯一)等。

  • 加权求平均值

    http://112.74.48.31:9200/customer/_search?size=0											-GET
    {
        "aggs" : {
            "metoo_weighted": {
                "weighted_avg": {
                    "value": {
                        "field": "age"
                    },
                    "weight": {
                        "field": "grade"
                    }
                }
            }
        }
    }
    
    

    在一些特定场景我们可以能需要用到加权平均,例如我们在统计全国的平均成绩,每个省份总分都是一样的,但是由于每个省份的试卷难度不同,可能上海的试卷要难一点,在现有分数上要加上当前成绩的0.2(权重),北京的试卷简单一点在当前成绩上减去0.2,那么我们就需要使用到:weighted_avg,加权平均。(这里帅途使用age为平均数据,grade为权重数据,计算age加权之后的平均值)

    查看返回值

    {
        "took": 14,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "metoo_weighted": { 	-- 加权平均之后的值,加权平均虽然我们在条件桶中写了两个参数,但是返回值是一个值。
                "value": 34.973333333333336
            }
        }
    }
    
    • 多值聚合
    http://112.74.48.31:9200/customer/_search?size=0											-GET
    {
        "aggs" : {
            "metoo_stats" : {
                "stats" : {  -- 统计聚合,查询多种聚合值,返回值在一个桶中
                    "field" : "age" 
                } 
            }
        }
    }
    
    

    查询统计聚合返回值解析

    	{
        "took": 1,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "metoo_stats": { --统计聚合返回值,包含基础查询返回值
                "count": 10,
                "min": 18.0,
                "max": 58.0,
                "avg": 30.0,
                "sum": 300.0
            }
        }
    }
    
  • 拓展统计

    http://112.74.48.31:9200/customer/_search?size=0											-GET
    {
        "aggs" : {
            "metoo_extended_stats" : { --对统计集合的拓展,比统计聚合返回值更全面
                "extended_stats" : {
                    "field" : "age" 
                } 
            }
        }
    }
    
    
7、Matrix聚合
  • 矩阵统计

    http://112.74.48.31:9200/customer/_search?size=0											-GET
    {
        "aggs": {
            "metoo_matrix_stats": {
                "matrix_stats": {    -- 矩阵统计关键字
                    "fields": ["age", "grade"]  --我们对age和grade两个字段进行统计
                }
            }
        }
    }
    

    矩阵统计目前处于测试阶段,在后期的发型版本中可能被完全修改或者删除,其实矩阵统计就是在原来metric统计聚合的基础上增加了多字段进行统计。下面附上返回值视图。第一行为字段grade的拓展统计数据,第二行为字段age的拓展统计数据。
    在这里插入图片描述

    更具上面我们可以看出,返回值结果生成了一个数据矩阵,下面我们查看json返回值

    {
        "took": 2,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "metoo_matrix_stats": {
                "doc_count": 10,  -- 检索文档数量
                "fields": [ -- 统计字段参数数组
                    {  -- 每个字段的统计数据
                        "name": "grade",  
                        "count": 10,
                        "mean": 68.30000000000001,
                        "variance": 939.5666666666667,
                        "skewness": -1.0970876343301157,
                        "kurtosis": 3.4328633556223305,
                        "covariance": {
                            "grade": 939.5666666666667,
                            "age": -40.088888888888896
                        },
                        "correlation": {
                            "grade": 1.0,
                            "age": -0.09900937761061816
                        }
                    },
                    {
                        "name": "age",
                        "count": 10,
                        "mean": 29.600000000000005,
                        "variance": 174.4888888888889,
                        "skewness": 0.9785339698632999,
                        "kurtosis": 2.9787389943709,
                        "covariance": {
                            "grade": -40.088888888888896,
                            "age": 174.4888888888889
                        },
                        "correlation": {
                            "grade": -0.09900937761061816,
                            "age": 1.0
                        }
                    }
                ]
            }
        }
    }
    
8、Pipeline聚合
  • Parent聚合
    Bucket Sort Aggregation聚合,父级管道聚合,对父级管道的输出结果进行分组,同时也可以排序

    {
        "size": 0,
        "aggs" : {
            "one_aggs" : {  --第一个聚合根据性别分组
                "terms" : {
                    "field" : "gender"
                },
                "aggs": {
                    "tow_aggs": {  --第二个聚合,分组之后求出男女年龄平均值
                        "avg": {
                            "field": "age"
                        }
                    },
                    "three_aggs": {	--第三个聚合将第二聚合的输出作为参数,进行排序。
                        "bucket_sort": {
                            "sort": [
                              {"tow_aggs": {"order": "asc"}}  --正序
                            ],
                            "from":0,  --- 分页参数,从第一页开始,每页展示三条数据,如果父聚合输出过多可以从这里截断
                            "size": 3 --分页默认从0开始
                        }
                    }
                }
            }
        }
    }
    

    参数值解析

    {
        "took": 1,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "one_aggs": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [  -- 父级管道,不会生成新桶,在父桶基础上加强数据
                    {
                        "key": "女",
                        "doc_count": 5,
                        "tow_aggs": {
                            "value": 25.0
                        }
                    },
                    {
                        "key": "男",
                        "doc_count": 5,
                        "tow_aggs": {
                            "value": 34.2
                        }
                    }
                ]
            }
        }
    }
    
  • Sibling聚合
    Avg Bucket Aggregation聚合,同级管道聚合,主要用于指标聚合,求平均值

    {
    	  "size": 0,
    	  "aggs": {
    	    "one_aggs": {        -- 第一个聚合,根据性别分组         
    	           "terms": {
    	            "field": "gender"
    	      },	
    	      "aggs": {           -- 第二个聚合,分组之后分别求出男和女的总年龄                         
    	        "tow_aggs": {
    	          "sum": {
    	            "field": "age"
    	          }
    	        }
    	      }
    	    },
    	    "three_aggs": {       --第三个聚合 Avg Bucket Aggregation求出男和女总年龄的平均值
    	      "avg_bucket": {
    	        "buckets_path": "one_aggs>tow_aggs" 
    	      }
    	    }
    	  }
    }
    

    返回值解析

    {
        "took": 92,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 10,
                "relation": "eq"
            },
            "max_score": null,
            "hits": []
        },
        "aggregations": {
            "one_aggs": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [    --前两个聚合的返回值
                    {
                        "key": "女",
                        "doc_count": 5,
                        "tow_aggs": {
                            "value": 125.0
                        }
                    },
                    {
                        "key": "男",
                        "doc_count": 5,
                        "tow_aggs": {
                            "value": 171.0
                        }
                    }
                ]
            },
            "three_aggs": {		--Avg Bucket Aggregation 求出的男女总年龄平均值
                "value": 148.0
            }
        }
    }
    

总结

帅途这里只是列举部分常用的聚合和一些特定的聚合,如果小伙伴们想要了解更多聚合可以参考es官方文档,里面列举了非常多的聚合,能够满足各位小伙伴开发所需。我们也需要明确一些基本概念,这样在面试的时候,面试官问道才能对答如流。
在这里插入图片描述

  • 1、es总共有4种类型聚合分别是:Bucketing(桶)、Metric(指标、度量)、Matrix(矩阵)、(Pipeline)管道
  • 2、Bucketing桶聚合可以嵌套,大桶里面可以套小桶对大桶的数据再次筛选。可以嵌套多层
  • 3、Metric指标聚合,指标聚合分为单值聚合与多值聚合,它里面是一些查询函数,类似于sql中的avg、sum等
  • 4、Matrix(矩阵聚合),目前在官方文档中矩阵聚合只有一种聚合方式,matrix_stats,它相当于Metric聚合中stats统计聚合,将单字段变成了多字段。返回数据矩阵(目前处于测试阶段,未来可能完全更改或删除)
  • 5、Pipeline管道聚合,管道聚合分为Parent父管道聚合,在父聚合的基础之上操作,返回值不会生成新桶,而是在原有桶内。Sibling兄弟管道聚合,对同级聚合进行操作,操作后的数据不会影响其他聚合的输出,会生成新的桶,使用兄弟管道聚合同级必须有两个或以上的聚合。

最后,希望本篇文章能对各位小伙伴有帮助,目前很多关于es的文章都是基于5.0或者更早之前写的。其实es5.0和7.0区别还是蛮大的不只是一些核心概念的弃用与删除,还有一些检索方面的优化与变动等。
在这里插入图片描述
看到这了快点赞关注一下吧!帅途祝所有点赞关注的小哥哥小姐姐工资涨5k,头发永远不会掉

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《再也不怕elasticsearch》es聚合使用与原理剖析 的相关文章

随机推荐

  • 禁用 第三方cookie 之后,百度统计会发生什么?

    禁用 第三方cookie 之后 经过亲测 结论是 不一定 百度统计还是有可能知道你是谁的 但可能失准 本想研究一下百度统计是如何统计数据的 发现基本上是利用cookie 大致情况是这样的 名称 用途 有效期 类型 HMACCOUNT Vis
  • Python之sys模块详解

    sys模块 sys 模块提供了许多函数和变量来处理 Python 运行时环境的不同部分 常见用法 sys argv 命令行参数List 第一个元素是程序本身路径 sys modules keys 返回所有已经导入的模块列表 sys exc
  • CAS5.3 服务器集成MySQL8数据库

    MySQL 相关准备 1 安装MySQL8 并安装相关数据库实例 省略一千字 2 新建ucas auth user表 并增加相关用户条记录 DROP TABLE IF EXISTS ucas auth user CREATE TABLE u
  • 解决tomcat安装配置后localhost 打不开

    为了这只丑猫能用的方法都用了 终于出来了 也不知道到底哪些是必须的 建议 1 检查端口8080是否被占用 被占用的话参照下方改端口 2 环境变量肯定是要配置的 3 如果以上不可以 那么什么方法都试试吧 前提 下载安装tomcat9和jdk
  • JAVA【设计模式】抽象工厂模式

    抽象工厂模式 一 定义 二 示例 传统硬编码方式 都在一个类里面实现 多重if else嵌套使用 抽象工厂模式 UML关系图 一 定义 抽象工厂模式 类似于动态代理对象的生成工厂 集中管理各个代理对象 使用代理对象解决实际业务场景 减少代码
  • Recall, Precision, AP, mAP的计算方法(看一次就懂系列)

    Recall Precision AP mAP的计算方法 看一次就懂系列 mAP全称是mean Average Precision 这里的Average Precision 是在不同recall下计算得到的 所以要知道什么是mAP 要先了解
  • Linux命令的详解

    配置ip 防火墙 setup linux查看ip ifconfig 重启网路 service network restart 查看文件 ls查看当前目录的文件内容 ll查看当前目录的详细内容 ll a a 表示查看全部内容 包括隐藏文件 测
  • 重试框架 Spring-Retry 和 Guava-Retry,你知道该怎么选吗?

    一 重试框架之Spring Retry Spring Retry 为 Spring 应用程序提供了声明性重试支持 它用于Spring批处理 Spring集成 Apache Hadoop 等等 它主要是针对可能抛出异常的一些调用操作 进行有策
  • mysql-8.0.11-win64安装教程

    1 下载mysql安装包 下载链接 https pan baidu com s 12eEZXxmBBEbpI5FXVaJ7bQ 提取码 t3j2 2 新建一个mysql文件夹 将压缩包解压到文件夹中 3 配置my ini文件 新建一个my
  • 小波滤波器与其他滤波器的区别_视界,输入滤波器常见的问题以及解决方法

    随着信息时代的进步与发展 输入滤波器应用范围也得到了广泛应用 它适用于数据处理系统 电信系统 电源 电梯行业 变频器及电源净化等需要强干扰抑制器设备中 在选择该产品的时候难免会遇到一些问题 下面是小编整理的有关输入滤波器的常见问题 以及处理
  • 题目 1162: 密码

    网上流传一句话 常在网上飘啊 哪能不挨刀啊 其实要想能安安心心地上网其实也不难 学点安全知识就可以 首先 我们就要设置一个安全的密码 那什么样的密码才叫安全的呢 一般来说一个比较安全的密码至少应该满足下面两个条件 1 密码长度大于等于8 且
  • SpringCloud Netflix Hystrix

    文章目录 一 Hystrix简介 1 什么是灾难性雪崩效应 2 什么是Hystrix 二 服务降级 Ribbon中 三 服务熔断 Ribbon中 服务降级的强化版 四 请求缓存 Ribbon中 不推荐 查询频率高 修改频率低时谨慎使用 五
  • syncthing数据同步应用-docker部署

    syncthing应用场景类似于rsync 在数据传输通道的两端都部署服务 再通过密钥验证的方式完成最终数据同步 而syncthing较之更加简单 因配备了Web UI 配置上难度降低了不少 相关资料 https syncthing net
  • go语言命令行库的安装与使用 -- cobra

    文章目录 前言 一 go env的配置 镜像源的设置 GOPROXY 二 cobra的安装与cobra cli的安装 1 cobra的安装 1 测试是否安装成功 2 cobra cli的安装 cobra cli的使用 前言 看了许多cobr
  • Vue3.0+ts—watch使用

    引入Vue的对象 ref reactive watch ref 用来声明响应式的基础类型的变量 reactive用来声明响应式的对象类型的变量 watch 引入watch对象 以便调用 import ref reactive watch f
  • 若依框架添加页面步骤

    本文代码使用的是ruoyi分离版 http doc ruoyi vip ruoyi vue 一 导入表 1 1查看数据库表 1 2使用后台代码生成模块 二 编辑表信息 若依框架前后端分离版本自动生成代码的详细步骤 1 若依框架的下载和本地运
  • Java Web-servlet技术-通过表单向servlet提交数据

    通过表单向servlet提交数据 1 创建名为ComputeBill的servlet文件 2 重写init 和service package myservlet import java io IOException import java
  • 游戏服务器维护请更换服务器,更换游戏服务器

    更换游戏服务器 内容精选 换一换 支持 您可以先将弹性公网IP从原弹性云服务器解绑 如何解绑请参考解绑定和释放弹性公网IP 再将弹性公网IP绑定到目标弹性云服务器 如何绑定请参考绑定云资源 相关操作 为弹性云服务器更换绑定的弹性公网IP 请
  • Tomcat官网地址

    Tomcat官网地址 https tomcat apache org https tomcat apache org
  • 《再也不怕elasticsearch》es聚合使用与原理剖析

    大家好我是迷途 一个在互联网行业 摸爬滚打的学子 热爱学习 热爱代码 热爱技术 热爱互联网的一切 再也不怕elasticsearch系列 帅途会慢慢由浅入深 为大家剖析一遍 各位大佬请放心 虽然这个系列帅途有时候更新的有点慢 但是绝对不会烂