• Elasticsearch(8) --- 聚合查询(Metric聚合)


    聚合查询(Metric聚合)
    说明:该博客对于的Elasticsearch 的版本为7.3。

    在Mysql中,我们可以获取一组数据的 最大值(Max)、最小值(Min)。同样我们能够对这组数据进行 分组(Group)。那么对于Elasticsearch中

    我们也可以实现同样的功能,聚合有关资料官方文档内容较多,这里大概分两篇博客写这个有关Elasticsearch聚合。

    官方对聚合有四个关键字: Metric(指标)、Bucketing(桶)、Matrix(矩阵)、Pipeline(管道)。

    一、聚合概念

    1. ES聚合分析是什么?
      概念 Elasticsearch除全文检索功能外提供的针对Elasticsearch数据做统计分析的功能。它的实时性高,所有的计算结果都是即时返回。
      Elasticsearch将聚合分析主要分为如下4类:

    Metric(指标): 指标分析类型,如计算最大值、最小值、平均值等等 (对桶内的文档进行聚合分析的操作)
    Bucket(桶): 分桶类型,类似SQL中的GROUP BY语法 (满足特定条件的文档的集合)
    Pipeline(管道): 管道分析类型,基于上一级的聚合分析结果进行在分析
    Matrix(矩阵): 矩阵分析类型(聚合是一种面向数值型的聚合,用于计算一组文档字段中的统计信息)
    2.ES聚合分析查询的写法
    在查询请求体中以aggregations节点按如下语法定义聚合分析:

    "aggregations" : {
    "<aggregation_name>" : {
    "<aggregation_type>" : {
    <aggregation_body>
    }
    [,"meta" : { [<meta_data_body>] } ]?
    [,"aggregations" : { [<sub_aggregation>]+ } ]?
    }
    [,"<aggregation_name_2>" : { ... } ]*
    }
    说明:aggregations 也可简写为 aggs

    3、指标(metric)和 桶(bucket)
    虽然Elasticsearch有四种聚合方式,但在一般实际开发中,用到的比较多的就是Metric和Bucket。

    (1) 桶(bucket)  

      a、简单来说桶就是满足特定条件的文档的集合。

      b、当聚合开始被执行,每个文档里面的值通过计算来决定符合哪个桶的条件,如果匹配到,文档将放入相应的桶并接着开始聚合操作。

      c、桶也可以被嵌套在其他桶里面。

    (2)指标(metric)

      a、桶能让我们划分文档到有意义的集合,但是最终我们需要的是对这些桶内的文档进行一些指标的计算。分桶是一种达到目的地的手段:它提供了一种给文档分组的方法来让

    我们可以计算感兴趣的指标。

      b、大多数指标是简单的数学运算(如:最小值、平均值、最大值、汇总),这些是通过文档的值来计算的。

    二、指标(Metric)详解
    官网: 指标聚合官网文档:Metric

    Metric聚合分析分为单值分析和多值分析两类:

    1、单值分析,只输出一个分析结果

    min,max,avg,sum,cardinality

    2、多值分析,输出多个分析结果

    stats,extended_stats,percentile,percentile_rank,top hits
    1、Avg(平均值)
    计算从聚合文档中提取的数值的平均值。

    POST /exams/_search?size=0
    {
    "aggs" : {
    "avg_grade" : { "avg" : { "field" : "grade" } }
    }
    }
    2、Max(最大值)
    计算从聚合文档中提取的数值的最大值。

    POST /sales/_search?size=0
    {
    "aggs" : {
    "max_price" : { "max" : { "field" : "price" } }
    }
    }
    3、Min(最小值)
    计算从聚合文档中提取的数值的最小值。

    POST /sales/_search?size=0
    {
    "aggs" : {
    "min_price" : { "min" : { "field" : "price" } }
    }
    }
    4、Sum(总和)
    计算从聚合文档中提取的数值的总和。

    POST /sales/_search?size=0
    {
    "query" : {
    "constant_score" : {
    "filter" : {
    "match" : { "type" : "hat" }
    }
    }
    },
    "aggs" : {
    "hat_prices" : { "sum" : { "field" : "price" } }
    }
    }
    5、 Cardinality(唯一值)
    cardinality 求唯一值,即不重复的字段有多少(相当于mysql中的distinct)

    POST /sales/_search?size=0
    {
    "aggs" : {
    "type_count" : {
    "cardinality" : {
    "field" : "type"
    }
    }
    }
    }
    6、Stats
    stats 统计,请求后会直接显示多种聚合结果

    POST /exams/_search?size=0
    {
    "aggs" : {
    "grades_stats" : { "stats" : { "field" : "grade" } }
    }
    }
    返回

    {
    ...
    "aggregations": {
    "grades_stats": {
    "count": 2,
    "min": 50.0,
    "max": 100.0,
    "avg": 75.0,
    "sum": 150.0
    }
    }
    }
    7、Percentiles
    对指定字段的值按从小到大累计每个值对应的文档数的占比,返回指定占比比例对应的值。

    1)默认取百分比

    默认按照[ 1, 5, 25, 50, 75, 95, 99 ]来统计

    GET latency/_search
    {
    "size": 0,
    "aggs" : {
    "load_time_outlier" : {
    "percentiles" : {
    "field" : "load_time"
    }
    }
    }
    }
    返回结果可以理解为:占比为50%的文档的age值 <= 445,或反过来:age<=445的文档数占总命中文档数的50%

    {
    ...
    "aggregations": {
    "load_time_outlier": {
    "values" : {
    "1.0": 5.0,
    "5.0": 25.0,
    "25.0": 165.0,
    "50.0": 445.0,
    "75.0": 725.0,
    "95.0": 945.0,
    "99.0": 985.0
    }
    }
    }
    }
    2)指定分位值

    GET latency/_search
    {
    "size": 0,
    "aggs" : {
    "load_time_outlier" : {
    "percentiles" : {
    "field" : "load_time",
    "percents" : [95, 99, 99.9]
    }
    }
    }
    }
    Keyed Response
    默认情况下,keyed标志设置为true,它将唯一的字符串键与每个存储桶相关联,并将范围作为哈希而不是数组返回。

    GET latency/_search
    {
    "size": 0,
    "aggs": {
    "load_time_outlier": {
    "percentiles": {
    "field": "load_time",
    "keyed": false
    }
    }
    }
    }
    返回结果

    {
    ...
    "aggregations": {
    "load_time_outlier": {
    "values": [
    {
    "key": 1.0,
    "value": 5.0
    },
    {
    "key": 5.0,
    "value": 25.0
    },
    {
    "key": 25.0,
    "value": 165.0
    },
    {
    "key": 50.0,
    "value": 445.0
    },
    {
    "key": 75.0,
    "value": 725.0
    },
    {
    "key": 95.0,
    "value": 945.0
    },
    {
    "key": 99.0,
    "value": 985.0
    }
    ]
    }
    }
    }
    8、 Percentile Ranks
    上面是通过百分比求文档值,这里通过文档值求百分比。

    GET latency/_search
    {
    "size": 0,
    "aggs" : {
    "load_time_ranks" : {
    "percentile_ranks" : {
    "field" : "load_time",
    "values" : [500, 600]
    }
    }
    }
    }
    返回结果

    {
    ...
    "aggregations": {
    "load_time_ranks": {
    "values" : {
    "500.0": 55.1,
    "600.0": 64.0
    }
    }
    }
    }
    结果说明:时间小于500的文档占比为55.1%,时间小于600的文档占比为64%,

    9、Top Hits
    一般用于分桶后获取该桶内匹配前n的文档列表

    POST /sales/_search?size=0
    {
    "aggs": {
    "top_tags": {
    "terms": {
    "field": "type", #根据type进行分组 每组显示前3个文档
    "size": 3
    },
    "aggs": {
    "top_sales_hits": {
    "top_hits": {
    "sort": [
    {
    "date": {
    "order": "desc" #按照时间进行倒叙排序
    }
    }
    ],
    "_source": {
    "includes": [ "date", "price" ] #只显示文档指定字段
    },
    "size" : 1
    }
    }
    }
    }
    }
    }

    三、示例
    下面会针对上面官方文档的例子进行举例说明。

    1、添加测试数据
    1)创建索引

    DELETE /employees
    PUT /employees/
    {
    "mappings" : {
    "properties" : {
    "age" : {
    "type" : "integer"
    },
    "gender" : {
    "type" : "keyword"
    },
    "job" : {
    "type" : "text",
    "fields" : {
    "keyword" : {
    "type" : "keyword",
    "ignore_above" : 50
    }
    }
    },
    "name" : {
    "type" : "keyword"
    },
    "salary" : {
    "type" : "integer"
    }
    }
    }
    }
    2)添加数据

    添加10条数据,每条数据包含:姓名、年龄、工作、性别、薪资

    PUT /employees/_bulk
    { "index" : { "_id" : "1" } }
    { "name" : "Emma","age":32,"job":"Product Manager","gender":"female","salary":35000 }
    { "index" : { "_id" : "2" } }
    { "name" : "Underwood","age":41,"job":"Dev Manager","gender":"male","salary": 50000}
    { "index" : { "_id" : "3" } }
    { "name" : "Tran","age":25,"job":"Web Designer","gender":"male","salary":18000 }
    { "index" : { "_id" : "4" } }
    { "name" : "Rivera","age":26,"job":"Web Designer","gender":"female","salary": 22000}
    { "index" : { "_id" : "5" } }
    { "name" : "Rose","age":25,"job":"QA","gender":"female","salary":18000 }
    { "index" : { "_id" : "6" } }
    { "name" : "Lucy","age":31,"job":"QA","gender":"female","salary": 25000}
    { "index" : { "_id" : "7" } }
    { "name" : "Byrd","age":27,"job":"QA","gender":"male","salary":20000 }
    { "index" : { "_id" : "8" } }
    { "name" : "Foster","age":27,"job":"Java Programmer","gender":"male","salary": 20000}
    { "index" : { "_id" : "9" } }
    { "name" : "Gregory","age":32,"job":"Java Programmer","gender":"male","salary":22000 }
    { "index" : { "_id" : "10" } }
    { "name" : "Bryant","age":20,"job":"Java Programmer","gender":"male","salary": 9000}
    2、求薪资最低值
    POST employees/_search
    {
    "size": 0,
    "aggs": {
    "min_salary": {
    "min": {
    "field":"salary"
    }
    }
    }
    }
    返回

    3、找到最低、最高和平均工资
    POST employees/_search
    {
    "size": 0,
    "aggs": {
    "max_salary": {
    "max": {
    "field": "salary"
    }
    },
    "min_salary": {
    "min": {
    "field": "salary"
    }
    },
    "avg_salary": {
    "avg": {
    "field": "salary"
    }
    }
    }
    }
    4、一个聚合,输出多值
    POST employees/_search
    {
    "size": 0,
    "aggs": {
    "stats_salary": {
    "stats": {
    "field":"salary"
    }
    }
    }
    }
    返回

    5、求一共有多少工作类型
    POST employees/_search
    {
    "size": 0,
    "aggs": {
    "cardinate": {
    "cardinality": {
    "field": "job.keyword"
    }
    }
    }
    }
    返回

    注意 我们需要把job的类型为keyword类型,这样就不会分词,把它当成一个整体。

    6、查看中位数的薪资
    POST employees/_search
    {
    "size": 0,
    "aggs": {
    "load_time_outlier": {
    "percentiles": {
    "field": "salary",
    "percents" : [50, 99],
    "keyed": false
    }
    }
    }
    }
    返回

    发现这些工作的中位数是:21000元。

    7、取每个工作类型薪资最高的数据
    多层嵌套 根据工作类型分桶,然后按照性别分桶,计算每个桶中工资的最高的薪资。

    POST employees/_search
    {
    "size": 0,
    "aggs": {
    "Job_gender_stats": {
    "terms": {
    "field": "job.keyword"
    },
    "aggs": {
    "gender_stats": {
    "terms": {
    "field": "gender"
    },
    "aggs": {
    "salary_stats": {
    "max": {
    "field": "salary"
    }
    }
    }
    }
    }
    }
    }
    }
    返回

  • 相关阅读:
    cocos3.2触摸事件接收顺序
    触摸点是否在按钮矩形内
    scrollview里container拖动显示问题
    cocos2dx 显示对象尺寸
    allocating an object of abstract class
    学习scorllview
    cocos2dx引用计数
    addchild 报错不能添加nil
    有用的宏
    一段SQL
  • 原文地址:https://www.cnblogs.com/blogabc/p/12745028.html
Copyright © 2020-2023  润新知