赞
踩
Elasticsearch除搜索以外,提供了针对ES 数据进行统计分析的功能。聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:
使用场景
聚合查询可以用于各种场景,比如商业智能、数据挖掘、日志分析等等。
电商平台的销售分析:统计每个地区的销售额、每个用户的消费总额、每个产品的销售量等,以便更好地了解销售情况和趋势。
社交媒体的用户行为分析:统计每个用户的发布次数、转发次数、评论次数等,以便更好地了解用户行为和趋势,同时可以将数据按照地区、时间、话题等维度进行分析。
物流企业的运输分析:统计每个区域的运输量、每个车辆的运输次数、每个司机的行驶里程等,以便更好地了解运输情况和优化运输效率。
金融企业的交易分析:统计每个客户的交易总额、每个产品的销售量、每个交易员的业绩等,以便更好地了解交易情况和优化业务流程。
智能家居的设备监控分析:统计每个设备的使用次数、每个家庭的能源消耗量、每个时间段的设备使用率等,以便更好地了解用户需求和优化设备效能。
基本语法
聚合查询的语法结构与其他查询相似,通常包含以下部分:
- GET <index_name>/_search
- {
- "aggs": {
- "<aggs_name>": { // 聚合名称需要自己定义
- "<agg_type>": {
- "field": "<field_name>"
- }
- }
- }
- }
- // aggs_name:聚合函数的名称
- // agg_type:聚合种类,比如是桶聚合(terms)或者是指标聚合(avg、sum、min、max等)
- // field_name:字段名称或者叫域名。
- SELECT MIN(price), MAX(price) FROM products
- #Metric聚合的DSL类比实现:
- {
- "aggs":{
- "avg_price":{
- "avg":{
- "field":"price"
- }
- }
- }
- }
- SELECT size COUNT(*) FROM products GROUP BY size
- #bucket聚合的DSL类比实现:
- {
- "aggs": {
- "by_size": {
- "terms": {
- "field": "size"
- }
- }
- }
示例数据
- 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"
- }
- }
- }
- }
-
- 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}
- { "index" : { "_id" : "11" } }
- { "name" : "Jenny","age":36,"job":"Java Programmer","gender":"female","salary":38000 }
- { "index" : { "_id" : "12" } }
- { "name" : "Mcdonald","age":31,"job":"Java Programmer","gender":"male","salary": 32000}
- { "index" : { "_id" : "13" } }
- { "name" : "Jonthna","age":30,"job":"Java Programmer","gender":"female","salary":30000 }
- { "index" : { "_id" : "14" } }
- { "name" : "Marshall","age":32,"job":"Javascript Programmer","gender":"male","salary": 25000}
- { "index" : { "_id" : "15" } }
- { "name" : "King","age":33,"job":"Java Programmer","gender":"male","salary":28000 }
- { "index" : { "_id" : "16" } }
- { "name" : "Mccarthy","age":21,"job":"Javascript Programmer","gender":"male","salary": 16000}
- { "index" : { "_id" : "17" } }
- { "name" : "Goodwin","age":25,"job":"Javascript Programmer","gender":"male","salary": 16000}
- { "index" : { "_id" : "18" } }
- { "name" : "Catherine","age":29,"job":"Javascript Programmer","gender":"female","salary": 20000}
- { "index" : { "_id" : "19" } }
- { "name" : "Boone","age":30,"job":"DBA","gender":"male","salary": 30000}
- { "index" : { "_id" : "20" } }
- { "name" : "Kathy","age":29,"job":"DBA","gender":"female","salary": 20000}

- #多个 Metric 聚合,找到最低最高和平均工资
- GET /employees/_search
- {
- "size": 0,
- "aggs": {
- "max_salary": {
- "max": {
- "field": "salary"
- }
- },
- "min_salary": {
- "min": {
- "field": "salary"
- }
- },
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- }
- }
- }

- # 一个聚合,输出多值
- GET /employees/_search
- {
- "size": 0,
- "aggs": {
- "stats_salary": {
- "stats": {
- "field":"salary"
- }
- }
- }
- }
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "cardinate": {
- "cardinality": {
- "field": "job.keyword"
- }
- }
- }
- }
按照一定的规则,将文档分配到不同的桶中,从而达到分类的目的。ES提供的一些常见的 Bucket Aggregation。
桶聚合可以用于各种场景,例如:
- # 对keword 进行聚合
- GET /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword"
- }
- }
- }
- }
聚合可配置属性有:
默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。我们可以指定order属性,自定义聚合的排序方式:
- GET /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword",
- "size": 10,
- "order": {
- "_count": "desc"
- }
- }
- }
- }
- }
- #只对salary在10000元以上的文档聚合
- GET /employees/_search
- {
- "query": {
- "range": {
- "salary": {
- "gte": 10000
- }
- }
- },
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword",
- "size": 10,
- "order": {
- "_count": "desc"
- }
- }
- }
- }
- }

注意:对 Text 字段进行 terms 聚合查询,会失败抛出异常。
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job"
- }
- }
- }
- }
解决办法:对 Text 字段打开 fielddata,支持terms aggregation
- PUT /employees/_mapping
- {
- "properties" : {
- "job":{
- "type": "text",
- "fielddata": true
- }
- }
- }
-
- # 对 Text 字段进行分词,分词后的terms
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job"
- }
- }
- }
- }

对job.keyword 和 job 进行 terms 聚合,分桶的总数并不一样。
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "cardinate": {
- "cardinality": {
- "field": "job"
- }
- }
- }
- }
- Salary Range分桶,可以自己定义 key
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "salary_range": {
- "range": {
- "field":"salary",
- "ranges":[
- {
- "to":10000
- },
- {
- "from":10000,
- "to":20000
- },
- {
- "key":">20000",
- "from":20000
- }
- ]
- }
- }
- }
- }

- #工资0到10万,以 5000一个区间进行分桶
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "salary_histrogram": {
- "histogram": {
- "field":"salary",
- "interval":5000,
- "extended_bounds":{
- "min":0,
- "max":100000
- }
- }
- }
- }
- }

- # 指定size,不同工种中,年纪最大的3个员工的具体信息
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword"
- },
- "aggs":{
- "old_employee":{
- "top_hits":{
- "size":3,
- "sort":[
- {
- "age":{
- "order":"desc"
- }
- }
- ]
- }
- }
- }
- }
- }
- }

支持对聚合分析的结果,再次进行聚合分析。
Pipeline 的分析结果会输出到原结果中,根据位置的不同,分为两类:
在员工数最多的工种里,找出平均工资最低的工种。
- # 平均工资最低的工种
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword",
- "size": 10
- },
- "aggs": {
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- }
- }
- },
- "min_salary_by_job":{
- "min_bucket": {
- "buckets_path": "jobs>avg_salary"
- }
- }
- }
- }

- # 平均工资的统计分析
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword",
- "size": 10
- },
- "aggs": {
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- }
- }
- },
- "stats_salary_by_job":{
- "stats_bucket": {
- "buckets_path": "jobs>avg_salary"
- }
- }
- }
- }

- # 平均工资的百分位数
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword",
- "size": 10
- },
- "aggs": {
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- }
- }
- },
- "percentiles_salary_by_job":{
- "percentiles_bucket": {
- "buckets_path": "jobs>avg_salary"
- }
- }
- }
- }

- #Cumulative_sum 累计求和
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "age": {
- "histogram": {
- "field": "age",
- "min_doc_count": 0,
- "interval": 1
- },
- "aggs": {
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- },
- "cumulative_salary":{
- "cumulative_sum": {
- "buckets_path": "avg_salary"
- }
- }
- }
- }
- }
- }

ES聚合分析的默认作用范围是query的查询结果集,同时ES还支持以下方式改变聚合的作用范围:
- #Query
- POST employees/_search
- {
- "size": 0,
- "query": {
- "range": {
- "age": {
- "gte": 20
- }
- }
- },
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword"
-
- }
- }
- }
- }
-
- #Filter
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "older_person": {
- "filter":{
- "range":{
- "age":{
- "from":35
- }
- }
- },
- "aggs":{
- "jobs":{
- "terms": {
- "field":"job.keyword"
- }
- }
- }},
- "all_jobs": {
- "terms": {
- "field":"job.keyword"
-
- }
- }
- }
- }
-
- #Post field. 一条语句,找出所有的job类型。还能找到聚合后符合条件的结果
- POST employees/_search
- {
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword"
- }
- }
- },
- "post_filter": {
- "match": {
- "job.keyword": "Dev Manager"
- }
- }
- }
-
- #global
- POST employees/_search
- {
- "size": 0,
- "query": {
- "range": {
- "age": {
- "gte": 40
- }
- }
- },
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword"
-
- }
- },
- "all":{
- "global":{},
- "aggs":{
- "salary_avg":{
- "avg":{
- "field":"salary"
- }
- }
- }
- }
- }
- }

指定order,按照count和key进行排序:
- #排序 order
- #count and key
- POST employees/_search
- {
- "size": 0,
- "query": {
- "range": {
- "age": {
- "gte": 20
- }
- }
- },
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword",
- "order":[
- {"_count":"asc"},
- {"_key":"desc"}
- ]
- }
- }
- }
- }
-
- #排序 order
- #count and key
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword",
- "order":[ {
- "avg_salary":"desc"
- }]
- },
- "aggs": {
- "avg_salary": {
- "avg": {
- "field":"salary"
- }
- }
- }
- }
- }
- }
-
- #排序 order
- #count and key
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword",
- "order":[ {
- "stats_salary.min":"desc"
- }]
- },
- "aggs": {
- "stats_salary": {
- "stats": {
- "field":"salary"
- }
- }
- }
- }
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。