您的当前位置:首页正文

(八)elasticsearch之聚合分析的简单介绍

2024-11-20 来源:个人技术集锦

一、聚合分析的简单介绍

  • 聚合分析,英文为 Aggregation,是es 除搜索功能外提供的针对es数据做统计分析的功能。
  • es聚合分析功能丰富,提供 Bucket、Metric、Pipeline等多种分析方式,可以满足大部分的分析需求;
  • 实时性高,所有的计算结果是即时返回的,而Hadoop 等大数据系统一般都是 T+1 级别的。
  • 语法如下:
GET testindex/_search
{
    "size": 0,
    "aggs": {								// 关键词,与query 同级
        "agg_name": {						// 自定义的聚合名称
            "agg_type": {					// 聚合分析的定义,包含type 和 body 定义
                "agg_body"
            },
            [,"aggs": {"sub_agg"}]			// 子聚合
        },
        "agg_name2": {....}					// 可以包含多个聚合
    }
}

二、聚合分析之分类

  • Bucket,分桶类型,类似 SQL 中的 group by 语法;
  • Metric,指标分析类型,如计算最大值、最小值、平均值等;
  • Pipeline,管道分析类型,基于上一级的聚合分析结果进行再分析;
  • Matrix,矩阵分析类型。

三、Bucket 聚合分析

Bucket,意味 ’桶‘,即按照一定的规则将文档分配到不同的桶中,达到分类的目的。

按照Bucket 的分桶策略,常见的Bucket 聚合分析如下:

  • Terms:直接按照term来分桶。如果是text 类型(需要开启fielddata),则按照分词后的结果分桶。

  • Range:通过制定数值的范围内设定分桶规则

    // *-10000,10000-20000,20000-* 三个区间的文档数聚合
    GET testinde/_search
    {
        "aggs": {
            "salary_range": {
                "range": {
                    "field": "salary",
                    "ranges": [
                        {
                        	"key": "<10000"// 自定义key 值的名字
                            "to": 10000
                        },
                        {
                            "from": 10000,
                            "to": 20000,
                        },
                        {
                            "from": 20000
                        }
                    ]
                }
            }
        }
    }
    
  • Date Range:通过制定日期的范围来设定分桶规则

GET testindex/_search
{
    "aggs": {
        "date_range": {
            "range": {
                "field": "birth",
                "format": "yyyy-MM-dd",					// 指定返回结果的日期格式
                "ranges": [
                    {
                        "from": "2019-09-01",			// 指定日期范围,可以使用date match
                        "to": "2019-09-30"
                    }
                ]
            }
        }
    }
}
  • Histogram:直方图,以固定间隔的策略来分割数据
GET testindex/_search
{
    "aggs": {
        "salary_hist": {
            "histogram": {					// 关键词
                "field": "salary",
                "interval": 5000,			// 指定间隔大小
                "extended_bounds": {		// 指定数据范围
                    "min": 0,
                    "max": 50000
                }
            }
        }
    }
}
  • Date Histogram:针对日期的直方图或者柱状图,是时序数据分析中的常用聚合分析类型
GET testindex/_search
{
    "aggs": {
        "by_year": {
            "date_histogram": {					// 关键词
                "field": "birth",
                "interval": "year",			// 指定间隔大小
                "format": "yyyy"
            }
        }
    }
}

四、Metric 聚合分析

主要分如下2类:

  • 单值分析,只输出一个分析结果,常见的有min ,max ,avg ,sum , cardinality
  • 多值分析,输出多个分析结果,常见的有stats ,extended stats ,percentile , percentile rank ,top hits

1、cardinality

集合的势,或者基数,是指不同数值的个数。可以类比成 SQL 中的 distinct count意思。分组求和,比如某列的数值有多个不同的值。

2、stats

返回一系列数值类型的统计值,包含了min、max、avg、sum和count。一次做了多种分析。

3、extended_stats

顾名思义,是对stats的扩展,包含了更多的统计数据,如方差、标准差等。

4、percentiles与percentile_ranks

百分位数统计。如下:

// 比如:第一行的意思是18岁以下的人数占1.0%
{
    "took": 55,
    ......
    "aggregations": {
        "per_age": {
            "1.0": 18,
            "5.0": 25,
            "25.0": 29,
            "50.0": 31,
            "75.0": 40,
            "95.0": 60,
            "99.0": 80
        }
    }
}
// 指定展示的百分位数(只展示95%,99%,99.9%的数据)
GET testindex/_search
{
    "aggs": {
        "per_salary": {
            "percentiles": {
            	"field": "salary",
                "percents": [
                	95,
                	99,
                	99.9
                ]
            }
        }
    }
}

5、top_hits

一般用于分桶聚合后,获取该桶内最匹配的顶部文档列表,即详情数据。如下:

GET testindex/_search
{
    "aggs": {
        "group_jobs": {
            "terms": {						// 分桶聚合
                "field": "job.keyword"
            },
            "aggs": {
                "top_employee": {
                    "top_hits": {			// 关键词
                        "size": 10,
                        "sort": [
                            {
                                "age": {
                                    "order": "desc"
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
}

五、Bucket + Metric 聚合分析

Bucket 聚合分析允许通过添加子分析来进一步分析,该子分析可以是 Bucket 也可以是 Metric。

六、pipeline 聚合分析

pipeline的分析结果会输出到原结果中,根据输出位置的不同,可以分为2类。

1、parent 结果内嵌到现有的聚合分析结果中:

  • Derivative:计算Bucket 值的导数。
  • Moving Average:计算Bucket值的移动平均值。
  • Cumulative Sum:计算Bucket值的累计加和。

2、Sibling 结果与现有聚合分析结果同级

  • Max/Min/Avg/Sum Bucket
  • Stats/Extended Stats Bucket
  • Percentiles Bucket

七、聚合分析作用范围

es聚合分析默认作用范围是 query 的结果集,可以通过 filter、post_filter、global 改变其作用范围。

filter

它是为某个聚合分析设定过滤条件的,从而在不更改整体query 语句的情况下修改作用范围。

post_filter

作用于文档过滤,但在聚合分析后生效,过滤输出的结果。

global

无视query的过滤条件,基于全部文档进行分析。比如你在query里面进行了文档过滤,但是global还是会基于全部文档去分析。

八、排序

可以使用自带的关键数据进行排序,比如:

  • _count 文档数
  • _key 按照key值排序
GET testindex/_search
{
    "aggs": {
        "group_jobs": {
            "terms": {						// 分桶聚合
                "field": "job.keyword",
                "order": {					// 排序
                    "_count": "asc"
                }
            }
        }
    }
}

九、聚合分析精度问题

max、min这种是精确地,但是 terms 是不一定精确地。可以通过参数来优化它。

terms 聚合返回结果中有如下2个统计值:

  • doc_count_error_upper_bound 被遗漏的 term 可能的最大值
  • sum_other_doc_count 返回结果 bucket 的term外,其他term的文档总数

注:shard_size大小的设定方法

设定show_term_doc_count_error=true可以查看每个bucket误算的最大值。当其返回结果的doc_count_error_upper_bound=0,则说明计算是准确的,不存在误差。

GET testindex/_search
{
    "aggs": {
        "jobs": {
            "terms": {
                "field": "job.keyword",
                "show_term_doc_count_error": true
            }
        }
    }
}

shard_size默认大小如下:shard_size=size * 1.5 + 10

通过调整shard_size 的大小降低doc_count_error_upper_bound来提升准确度(随之而来的影响是增大了整体的计算量,从而降低了响应时间)

GET testindex/_search
{
    "aggs": {
        "jobs": {
            "terms": {
                "field": "job.keyword",
                "shard_size": 10,					// 关键词
                "show_term_doc_count_error": true
            }
        }
    }
}

十、热词分析(对热词内容先分词再聚合)

第一步,设置mapping(指定分词器和开启fielddata,因为你想要分词,所以type毫无疑问是text)

PUT test
{
  "mappings": {
    "doc": {
      "properties": {
        "hello": {
          "type": "text", 
          "analyzer": "ik_max_word",
          "fielddata": true
        }
      }
    }
  }
}

第二步,插入测试数据

PUT test/doc/1
{
  "hello": "北京加油"
}

第三步,聚合查询

GET test/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "NAME": {
      "terms": {
        "field": "hello",
        "size": 10
      }
    }
  }
}

结果如下:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "test123",
        "_type": "doc",
        "_id": "1",
        "_score": 1,
        "_source": {
          "hello": "北京加油"
        }
      }
    ]
  },
  "aggregations": {
    "NAME": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "北京",
          "doc_count": 1
        },
        {
          "key": "加油",
          "doc_count": 1
        }
      ]
    }
  }
}
Top