ElasticSearch聚合分析API

来源:互联网 发布:下载网购淘宝网 编辑:程序博客网 时间:2024/05/29 10:07
aggs

前言

说完了ES的索引与检索,接着再介绍一个ES高级功能API – 聚合(Aggregations),聚合功能为ES注入了统计分析的血统,使用户在面对大数据提取统计指标时变得游刃有余。同样的工作,你在hadoop中可能需要写mapreduce或hive,在mongo中你必须得用大段的mapreduce脚本,而在ES中仅仅调用一个API就能实现了。

开始之前,提醒老司机们注意,ES原有的聚合功能Facets在新版本中将被正式被移除,抓紧时间用Aggregations替换Facets吧。Facets真的很慢!

1 关于Aggregations

Aggregations的部分特性类似于SQL语言中的group by,avg,sum等函数。但Aggregations API还提供了更加复杂的统计分析接口。

掌握Aggregations需要理解两个概念:

  • 桶(Buckets):符合条件的文档的集合,相当于SQL中的group by。比如,在users表中,按“地区”聚合,一个人将被分到北京桶或上海桶或其他桶里;按“性别”聚合,一个人将被分到男桶或女桶
  • 指标(Metrics):基于Buckets的基础上进行统计分析,相当于SQL中的count,avg,sum等。比如,按“地区”聚合,计算每个地区的人数,平均年龄等

对照一条SQL来加深我们的理解:

1
SELECT COUNT(color) FROM table GROUP BY color

GROUP BY相当于做分桶的工作,COUNT是统计指标。

下面介绍一些常用的Aggregations API。

2 Metrics

2.1 AVG

求均值。

1
2
3
4
5
6
GET /company/employee/_search
{
    "aggs" : {
        "avg_grade" : { "avg" : { "field" : "grade" } }
    }
}

执行结果

1
2
3
4
5
{
    "aggregations": {
        "avg_grade": {"value": 75}
    }
}

其他的简单统计API,如valuecount, max,min,sum作用与SQL中类似,就不一一解释了。

2.2 Cardinality

cardinality的作用是先执行类似SQL中的distinct操作,然后再统计排重后集合长度。得到的结果是一个近似值,因为考虑到在大量分片中排重的性能损耗Cardinality算法并不会load所有的数据。
1
2
3
4
5
6
7
{
    "aggs" : {
    "author_count" : {
        "cardinality" : {"field" : "author"}
    }
    }
}

2.3 Stats

返回聚合分析后所有有关stat的指标。具体哪些是stat指标是ES定义的,共有5项。

1
2
3
4
5
{
    "aggs" : {
    "grades_stats" : { "stats" : { "field" : "grade" } }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
{
    "aggregations": {
    "grades_stats": {
        "count": 6,
        "min": 60,
        "max": 98,
        "avg": 78.5,
        "sum": 471
    }
    }
}

2.4 Extended Stats

返回聚合分析后所有指标,比Stats多三个统计结果:平方和、方差、标准差

1
2
3
4
5
{
    "aggs" : {
    "grades_stats" : { "extended_stats" : { "field" : "grade" } }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "aggregations": {
    "grade_stats": {
        "count": 9,
        "min": 72,
        "max": 99,
        "avg": 86,
        "sum": 774,
        # 平方和
        "sum_of_squares": 67028,
        # 方差
        "variance": 51.55555555555556,
        # 标准差
        "std_deviation": 7.180219742846005,
        #平均加/减两个标准差的区间,用于可视化你的数据方差
        "std_deviation_bounds": {
        "upper": 100.36043948569201,
        "lower": 71.63956051430799
        }
    }
    }
}

2.5 Percentiles

百分位法统计,举例,运维人员记录了每次启动系统所需要的时间,或者,网站记录了每次用户访问的页面加载时间,然后对这些时间数据进行百分位法统计。我们在测试报告中经常会看到类似的统计数据

1
2
3
4
5
6
7
{
    "aggs" : {
    "load_time_outlier" : {
        "percentiles" : {"field" : "load_time"}
    }
    }
}

结果是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
    "aggregations": {
    "load_time_outlier": {
        "values" : {
        "1.0": 15,
        "5.0": 20,
        "25.0": 23,
        "50.0": 25,
        "75.0": 29,
        "95.0": 60,
        "99.0": 150
        }
    }
    }
}

加载时间在15ms内的占1%,20ms内的占5%,等等。

我们还可以指定百分位的指标,比如只想统计95%、99%、99.9%的加载时间

1
2
3
4
5
6
7
8
9
10
{
    "aggs" : {
    "load_time_outlier" : {
        "percentiles" : {
        "field" : "load_time",
        "percents" : [95, 99, 99.9]
        }
    }
    }
}

2.6 Percentile Ranks

Percentile API中,返回结果values中的key是固定的0-100间的值,而Percentile Ranks返回值中的value才是固定的,同样也是0到100。例如,我想知道加载时间是15ms与30ms的数据,在所有记录中处于什么水平,以这种方式反映数据在集合中的排名情况。

1
2
3
4
5
6
7
8
9
10
{
    "aggs" : {
    "load_time_outlier" : {
        "percentile_ranks" : {
        "field" : "load_time",
        "values" : [15, 30]
        }
    }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
{
    "aggregations": {
    "load_time_outlier": {
        "values" : {
        "15": 92,
        "30": 100
        }
    }
    }
}

3 Bucket

3.1 Filter

先过滤后聚合,类似SQL中的where,也有点象group by后加having。比如

1
2
3
4
5
6
7
8
9
10
{
    "aggs" : {
    "red_products" : {
        "filter" : { "term": { "color": "red" } },
        "aggs" : {
        "avg_price" : { "avg" : { "field" : "price" } }
        }
    }
    }
}

只统计红色衣服的均价。

3.2 Range

反映数据的分布情况,比如我想知道小于50,50到100,大于100的数据的个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    "aggs" : {
    "price_ranges" : {
        "range" : {
        "field" : "price",
        "ranges" : [
            { "to" : 50 },
            { "from" : 50, "to" : 100 },
            { "from" : 100 }
        ]
        }
    }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
{
    "aggregations": {
    "price_ranges" : {
        "buckets": [
        {"to": 50, "doc_count": 2},
        {"from": 50, "to": 100, "doc_count": 4},
        {"from": 100, "doc_count": 4}
        ]
    }
    }
}

3.3 Missing

我们想找出price字段值为空的文档的个数。

1
2
3
4
5
6
7
{
    "aggs" : {
    "products_without_a_price" : {
        "missing" : { "field" : "price" }
    }
    }
}

执行结果

1
2
3
4
5
6
7
{
    "aggs" : {
    "products_without_a_price" : {
        "doc_count" : 10
    }
    }
}

3.4 Terms

针对某个字段排重后统计个数。

1
2
3
4
5
6
7
{
    "aggs" : {
    "genders" : {
        "terms" : { "field" : "gender" }
    }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
12
{
    "aggregations" : {
    "genders" : {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 0,
        "buckets" : [
        {"key" : "male","doc_count" : 10},
        {"key" : "female","doc_count" : 10},
        ]
    }
    }
}

3.5 Date Range

针对日期型数据做分布统计。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    "aggs": {
    "range": {
        "date_range": {
        "field": "date",
        "format": "MM-yyy",
            "ranges": [
            { "to": "now-10M/M" },
            { "from": "now-10M/M" }
        ]
        }
    }
    }
}

这里的format参数是指定返回值的日期格式。

执行结果

1
2
3
4
5
6
7
8
9
10
{
    "aggregations": {
    "range": {
        "buckets": [
        {"to": 1.3437792E+12, "to_as_string": "08-2012","doc_count": 7},
        {"from": 1.3437792E+12, "from_as_string": "08-2012","doc_count": 2}
        ]
    }
    }
}

3.6 Global Aggregation

指定聚合的作用域与查询的作用域没有关联。因此返回结果中query命中的文档,与聚合的的统计结果是没有关系的。

1
2
3
4
5
6
7
8
9
10
11
12
13
{
    "query" : {
    "match" : { "title" : "shirt" }
    },
    "aggs" : {
    "all_products" : {
        "global" : {},
        "aggs" : {
        "avg_price" : { "avg" : { "field" : "price" } }
        }
    }
    }
}

3.7 Histogram

跟range类似,不过Histogram不需要你指定统计区间,只需要提供一个间隔区间的值。好象不太好理解,看个例子就全明白了。

比如,以50元为一个区间,统计每个区间内的价格分布

1
2
3
4
5
6
7
8
9
10
{
    "aggs" : {
    "prices" : {
        "histogram" : {
        "field" : "price",
        "interval" : 50
        }
    }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
12
{
    "aggregations": {
    "prices" : {
        "buckets": [
        {"key": 0, "doc_count": 2},
        {"key": 50, "doc_count": 4},
        {"key": 100, "doc_count": 0},
        {"key": 150, "doc_count": 3}
        ]
    }
    }
}

由于最高的价格没超过200元,因此最后的结果自动分为小于50,50到100,100到150,大于150共四个区间的值。

100到150区间的文档数为0个,我们想在返回结果中自动过滤该值,或者过滤偏小的值,可以添加一个参数”min_doc_count”,比如

1
2
3
4
5
6
7
8
9
10
11
{
    "aggs" : {
    "prices" : {
        "histogram" : {
        "field" : "price",
        "interval" : 50,
        "min_doc_count" : 1
        }
    }
    }
}

返回结果会自动将你设定的值以下的统计结果过滤出去。

3.8 Date Histogram

使用方法与Histogram类似,只是聚合的间隔区间是针对时间类型的字段。

1
2
3
4
5
6
7
8
9
10
11
{
    "aggs" : {
    "articles_over_time" : {
        "date_histogram" : {
        "field" : "date",
        "interval" : "1M",
        "format" : "yyyy-MM-dd"
        }
    }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
11
{
    "aggregations": {
    "articles_over_time": {
        "buckets": [
        {"key_as_string": "2013-02-02","key": 1328140800000, "doc_count": 1},
        {"key_as_string": "2013-03-02","key": 1330646400000, "doc_count": 2},
        ...
        ]
    }
    }
}

3.9 IPv4 range

由于ES是一个企业级的搜索和分析的解决方案,在做大量数据统计分析时比如用户访问行为数据,会采集用户的IP地址,类似这样的数据(还有地理位置数据等),ES也提供了最直接的统计接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
{
    "aggs" : {
    "ip_ranges" : {
        "ip_range" : {
        "field" : "ip",
        "ranges" : [
            { "to" : "10.0.0.5" },
            { "from" : "10.0.0.5" }
        ]
        }
    }
    }
}

执行结果

1
2
3
4
5
6
7
8
9
10
{
    "aggregations": {
    "ip_ranges": {
        "buckets" : [
        {"to": 167772165, "to_as_string": "10.0.0.5","doc_count": 4},
        {"from": 167772165,"from_as_string": "10.0.0.5","doc_count": 6}
        ]
    }
    }
}

3.10 Return only aggregation results

在统计分析时我们有时候并不需要知道命中了哪些文档,只需要将统计的结果返回给我们。因此我们可以在request body中添加配置参数size。

1
2
3
4
5
6
7
8
9
curl -XGET 'http://localhost:9200/twitter/tweet/_search' -d '{
    "size": 0,
        "aggregations": {
        "my_agg": {
            "terms": {"field": "text"}
            }
    }
}
'

4 聚合缓存

ES中经常使用到的聚合结果集可以被缓存起来,以便更快速的系统响应。这些缓存的结果集和你掠过缓存直接查询的结果是一样的。因为,第一次聚合的条件与结果缓存起来后,ES会判断你后续使用的聚合条件,如果聚合条件不变,并且检索的数据块未增更新,ES会自动返回缓存的结果。

注意聚合结果的缓存只针对size=0的请求(参考3.10章节),还有在聚合请求中使用了动态参数的比如Date Range中的now(参考3.5章节),ES同样不会缓存结果,因为聚合条件是动态的,即使缓存了结果也没用了。

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ps用替换颜色后怎么办 三星s8百度闪退怎么办 吃了过敏的东西怎么办 过敏了痒的厉害怎么办 脸吃麻辣过敏了怎么办 脸过敏发红痒怎么办急救 脸过敏怎么办快速治疗方法 下巴起噶的过敏怎么办 药物过敏脸肿了怎么办 吃虾过敏全身痒怎么办 全身过敏怎么办 痒的厉害 吃小龙虾过敏全身痒怎么办 脸过敏肿起来了怎么办 小孩对灰尘树木过敏怎么办 小孩过敏怎么办痒的很 脸皮肤过敏很痒怎么办 浅粉色绵羊皮衣不好清洗怎么办 皮料染上其他颜色怎么办 宝宝的银锁发黑怎么办 pu鞋子蹭坏了怎么办 包的油边脱胶了怎么办 pu包有点破皮怎么办 买房子不给过户怎么办 布艺床头有味道怎么办 皮革床头爆皮了怎么办 皮包用酒精擦了怎么办 床头靠背皮掉了怎么办 真皮床头爆皮了怎么办 半裙拉链往下滑怎么办 误用三氧化二砷怎么办 情侣之间感情淡了怎么办 雪纺布料刮坏了怎么办 棉麻布料坏了怎么办 主板针脚弯了怎么办?能修吗? 脸颊两侧毛孔大还有黑头怎么办 脸颊和鼻子粗毛孔大怎么办 十二时辰对照五脏养生在国外怎么办 在学校接吻怕被看到怎么办 楼房圈梁被破坏了怎么办 买了农村的房子怎么办 邻居建房不用共用墙怎么办