当前位置:   article > 正文

ElasticSearch聚合操作_es聚合操作

es聚合操作

Elasticsearch除搜索以外,提供了针对ES 数据进行统计分析的功能。聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

  • 什么品牌的手机最受欢迎?
  • 这些手机的平均价格、最高价格、最低价格?
  • 这些手机每月的销售情况如何?

使用场景

聚合查询可以用于各种场景,比如商业智能、数据挖掘、日志分析等等。

电商平台的销售分析:统计每个地区的销售额、每个用户的消费总额、每个产品的销售量等,以便更好地了解销售情况和趋势。

社交媒体的用户行为分析:统计每个用户的发布次数、转发次数、评论次数等,以便更好地了解用户行为和趋势,同时可以将数据按照地区、时间、话题等维度进行分析。

物流企业的运输分析:统计每个区域的运输量、每个车辆的运输次数、每个司机的行驶里程等,以便更好地了解运输情况和优化运输效率。

金融企业的交易分析:统计每个客户的交易总额、每个产品的销售量、每个交易员的业绩等,以便更好地了解交易情况和优化业务流程。

智能家居的设备监控分析:统计每个设备的使用次数、每个家庭的能源消耗量、每个时间段的设备使用率等,以便更好地了解用户需求和优化设备效能。

基本语法

聚合查询的语法结构与其他查询相似,通常包含以下部分:

  • 查询条件:指定需要聚合的文档,可以使用标准的 Elasticsearch 查询语法,如 term、match、range 等等。
  • 聚合函数:指定要执行的聚合操作,如 sum、avg、min、max、terms、date_histogram 等等。每个聚合命令都会生成一个聚合结果。
  • 聚合嵌套:聚合命令可以嵌套,以便更细粒度地分析数据。
  1. GET <index_name>/_search
  2. {
  3. "aggs": {
  4. "<aggs_name>": { // 聚合名称需要自己定义
  5. "<agg_type>": {
  6. "field": "<field_name>"
  7. }
  8. }
  9. }
  10. }
  11. // aggs_name:聚合函数的名称
  12. // agg_type:聚合种类,比如是桶聚合(terms)或者是指标聚合(avg、sum、min、max等)
  13. // field_name:字段名称或者叫域名。

1 聚合的分类

  • Metric Aggregation:—些数学运算,可以对文档字段进行统计分析,类比sql中的 min(), max(), sum() 操作。
  1. SELECT MIN(price), MAX(price) FROM products
  2. #Metric聚合的DSL类比实现:
  3. {
  4. "aggs":{
  5. "avg_price":{
  6. "avg":{
  7. "field":"price"
  8. }
  9. }
  10. }
  11. }
  • Bucket Aggregation: 一些满足特定条件的文档的集合放置到一个桶里,每一个桶关联一个key,类比sql中的group by操作。
  1. SELECT size COUNT(*) FROM products GROUP BY size
  2. #bucket聚合的DSL类比实现:
  3. {
  4. "aggs": {
  5. "by_size": {
  6. "terms": {
  7. "field": "size"
  8. }
  9. }
  10. }
  • Pipeline Aggregation:对其他的聚合结果进行二次聚合

示例数据

  1. DELETE /employees
  2. #创建索引库
  3. PUT /employees
  4. {
  5. "mappings": {
  6. "properties": {
  7. "age":{
  8. "type": "integer"
  9. },
  10. "gender":{
  11. "type": "keyword"
  12. },
  13. "job":{
  14. "type" : "text",
  15. "fields" : {
  16. "keyword" : {
  17. "type" : "keyword",
  18. "ignore_above" : 50
  19. }
  20. }
  21. },
  22. "name":{
  23. "type": "keyword"
  24. },
  25. "salary":{
  26. "type": "integer"
  27. }
  28. }
  29. }
  30. }
  31. PUT /employees/_bulk
  32. { "index" : { "_id" : "1" } }
  33. { "name" : "Emma","age":32,"job":"Product Manager","gender":"female","salary":35000 }
  34. { "index" : { "_id" : "2" } }
  35. { "name" : "Underwood","age":41,"job":"Dev Manager","gender":"male","salary": 50000}
  36. { "index" : { "_id" : "3" } }
  37. { "name" : "Tran","age":25,"job":"Web Designer","gender":"male","salary":18000 }
  38. { "index" : { "_id" : "4" } }
  39. { "name" : "Rivera","age":26,"job":"Web Designer","gender":"female","salary": 22000}
  40. { "index" : { "_id" : "5" } }
  41. { "name" : "Rose","age":25,"job":"QA","gender":"female","salary":18000 }
  42. { "index" : { "_id" : "6" } }
  43. { "name" : "Lucy","age":31,"job":"QA","gender":"female","salary": 25000}
  44. { "index" : { "_id" : "7" } }
  45. { "name" : "Byrd","age":27,"job":"QA","gender":"male","salary":20000 }
  46. { "index" : { "_id" : "8" } }
  47. { "name" : "Foster","age":27,"job":"Java Programmer","gender":"male","salary": 20000}
  48. { "index" : { "_id" : "9" } }
  49. { "name" : "Gregory","age":32,"job":"Java Programmer","gender":"male","salary":22000 }
  50. { "index" : { "_id" : "10" } }
  51. { "name" : "Bryant","age":20,"job":"Java Programmer","gender":"male","salary": 9000}
  52. { "index" : { "_id" : "11" } }
  53. { "name" : "Jenny","age":36,"job":"Java Programmer","gender":"female","salary":38000 }
  54. { "index" : { "_id" : "12" } }
  55. { "name" : "Mcdonald","age":31,"job":"Java Programmer","gender":"male","salary": 32000}
  56. { "index" : { "_id" : "13" } }
  57. { "name" : "Jonthna","age":30,"job":"Java Programmer","gender":"female","salary":30000 }
  58. { "index" : { "_id" : "14" } }
  59. { "name" : "Marshall","age":32,"job":"Javascript Programmer","gender":"male","salary": 25000}
  60. { "index" : { "_id" : "15" } }
  61. { "name" : "King","age":33,"job":"Java Programmer","gender":"male","salary":28000 }
  62. { "index" : { "_id" : "16" } }
  63. { "name" : "Mccarthy","age":21,"job":"Javascript Programmer","gender":"male","salary": 16000}
  64. { "index" : { "_id" : "17" } }
  65. { "name" : "Goodwin","age":25,"job":"Javascript Programmer","gender":"male","salary": 16000}
  66. { "index" : { "_id" : "18" } }
  67. { "name" : "Catherine","age":29,"job":"Javascript Programmer","gender":"female","salary": 20000}
  68. { "index" : { "_id" : "19" } }
  69. { "name" : "Boone","age":30,"job":"DBA","gender":"male","salary": 30000}
  70. { "index" : { "_id" : "20" } }
  71. { "name" : "Kathy","age":29,"job":"DBA","gender":"female","salary": 20000}

2 Metric Aggregation

  • 单值分析︰只输出一个分析结果
    • min, max, avg, sum
    • Cardinality(类似distinct Count)
  • 多值分析:输出多个分析结果
    •  stats(统计), extended stats
    • percentile (百分位), percentile rank
    • top hits(排在前面的示例) 
  1. 查询员工的最低最高和平均工资
  1. #多个 Metric 聚合,找到最低最高和平均工资
  2. GET /employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "max_salary": {
  7. "max": {
  8. "field": "salary"
  9. }
  10. },
  11. "min_salary": {
  12. "min": {
  13. "field": "salary"
  14. }
  15. },
  16. "avg_salary": {
  17. "avg": {
  18. "field": "salary"
  19. }
  20. }
  21. }
  22. }
  1. 对salary进行统计
  1. # 一个聚合,输出多值
  2. GET /employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "stats_salary": {
  7. "stats": {
  8. "field":"salary"
  9. }
  10. }
  11. }
  12. }
  1. cardinate对搜索结果去重
  1. POST /employees/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "cardinate": {
  6. "cardinality": {
  7. "field": "job.keyword"
  8. }
  9. }
  10. }
  11. }

3 Bucket Aggregation

按照一定的规则,将文档分配到不同的桶中,从而达到分类的目的。ES提供的一些常见的 Bucket Aggregation。

  • Terms,需要字段支持filedata
    • keyword 默认支持fielddata
    • text需要在Mapping 中开启fielddata,会按照分词后的结果进行分桶。
  • 数字类型
    • Range / Data Range
    • Histogram(直方图) / Date Histogram
  • 支持嵌套: 也就在桶里再做分桶

桶聚合可以用于各种场景,例如:

  • 对数据进行分组统计,比如按照地区、年龄段、性别等字段进行分组统计。
  • 对时间序列数据进行时间段分析,比如按照每小时、每天、每月、每季度、每年等时间段进行分析。
  • 对各种标签信息分类,并统计其数量。

3.1 获取job的分类信息

  1. # 对keword 进行聚合
  2. GET /employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "jobs": {
  7. "terms": {
  8. "field":"job.keyword"
  9. }
  10. }
  11. }
  12. }

聚合可配置属性有:

  • field:指定聚合字段
  • size:指定聚合结果数量
  • order:指定聚合结果排序方式

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。我们可以指定order属性,自定义聚合的排序方式:

  1. GET /employees/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "jobs": {
  6. "terms": {
  7. "field":"job.keyword",
  8. "size": 10,
  9. "order": {
  10. "_count": "desc"
  11. }
  12. }
  13. }
  14. }
  15. }

3.2 限定聚合范围

  1. #只对salary在10000元以上的文档聚合
  2. GET /employees/_search
  3. {
  4. "query": {
  5. "range": {
  6. "salary": {
  7. "gte": 10000
  8. }
  9. }
  10. },
  11. "size": 0,
  12. "aggs": {
  13. "jobs": {
  14. "terms": {
  15. "field":"job.keyword",
  16. "size": 10,
  17. "order": {
  18. "_count": "desc"
  19. }
  20. }
  21. }
  22. }
  23. }

注意:对 Text 字段进行 terms 聚合查询,会失败抛出异常。

  1. POST /employees/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "jobs": {
  6. "terms": {
  7. "field":"job"
  8. }
  9. }
  10. }
  11. }

解决办法:对 Text 字段打开 fielddata,支持terms aggregation

  1. PUT /employees/_mapping
  2. {
  3. "properties" : {
  4. "job":{
  5. "type": "text",
  6. "fielddata": true
  7. }
  8. }
  9. }
  10. # 对 Text 字段进行分词,分词后的terms
  11. POST /employees/_search
  12. {
  13. "size": 0,
  14. "aggs": {
  15. "jobs": {
  16. "terms": {
  17. "field":"job"
  18. }
  19. }
  20. }
  21. }

对job.keyword 和 job 进行 terms 聚合,分桶的总数并不一样。

  1. POST /employees/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "cardinate": {
  6. "cardinality": {
  7. "field": "job"
  8. }
  9. }
  10. }
  11. }

3.3 Range & Histogram聚合

  • 按照数字的范围,进行分桶;
  • 在Range Aggregation中,可以自定义Key。
  1. Range 示例:按照工资的 Range 分桶
  1. Salary Range分桶,可以自己定义 key
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "salary_range": {
  7. "range": {
  8. "field":"salary",
  9. "ranges":[
  10. {
  11. "to":10000
  12. },
  13. {
  14. "from":10000,
  15. "to":20000
  16. },
  17. {
  18. "key":">20000",
  19. "from":20000
  20. }
  21. ]
  22. }
  23. }
  24. }
  25. }
  1. Histogram示例:按照工资的间隔分桶
  1. #工资0到10万,以 5000一个区间进行分桶
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "salary_histrogram": {
  7. "histogram": {
  8. "field":"salary",
  9. "interval":5000,
  10. "extended_bounds":{
  11. "min":0,
  12. "max":100000
  13. }
  14. }
  15. }
  16. }
  17. }
  1. top_hits应用场景: 当获取分桶后,桶内最匹配的顶部文档列表;
  1. # 指定size,不同工种中,年纪最大的3个员工的具体信息
  2. POST /employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "jobs": {
  7. "terms": {
  8. "field":"job.keyword"
  9. },
  10. "aggs":{
  11. "old_employee":{
  12. "top_hits":{
  13. "size":3,
  14. "sort":[
  15. {
  16. "age":{
  17. "order":"desc"
  18. }
  19. }
  20. ]
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }

4 Pipeline Aggregation

支持对聚合分析的结果,再次进行聚合分析。

Pipeline 的分析结果会输出到原结果中,根据位置的不同,分为两类:

  • Sibling - 结果和现有分析结果同级
    • Max,min,Avg & Sum Bucket
    • Stats,Extended Status Bucket
    • Percentiles Bucket
  • Parent -结果内嵌到现有的聚合分析结果之中
    • Derivative(求导)
    • Cumultive Sum(累计求和)
    • Moving Function(移动平均值 )
  1. min_bucket示例

在员工数最多的工种里,找出平均工资最低的工种。

  1. # 平均工资最低的工种
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "jobs": {
  7. "terms": {
  8. "field": "job.keyword",
  9. "size": 10
  10. },
  11. "aggs": {
  12. "avg_salary": {
  13. "avg": {
  14. "field": "salary"
  15. }
  16. }
  17. }
  18. },
  19. "min_salary_by_job":{
  20. "min_bucket": {
  21. "buckets_path": "jobs>avg_salary"
  22. }
  23. }
  24. }
  25. }
  • min_salary_by_job结果和jobs的聚合同级
  • min_bucket求之前结果的最小值
  • 通过bucket_path关键字指定路径
  1. Stats示例
  1. # 平均工资的统计分析
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "jobs": {
  7. "terms": {
  8. "field": "job.keyword",
  9. "size": 10
  10. },
  11. "aggs": {
  12. "avg_salary": {
  13. "avg": {
  14. "field": "salary"
  15. }
  16. }
  17. }
  18. },
  19. "stats_salary_by_job":{
  20. "stats_bucket": {
  21. "buckets_path": "jobs>avg_salary"
  22. }
  23. }
  24. }
  25. }
  1. percentiles示例
  1. # 平均工资的百分位数
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "jobs": {
  7. "terms": {
  8. "field": "job.keyword",
  9. "size": 10
  10. },
  11. "aggs": {
  12. "avg_salary": {
  13. "avg": {
  14. "field": "salary"
  15. }
  16. }
  17. }
  18. },
  19. "percentiles_salary_by_job":{
  20. "percentiles_bucket": {
  21. "buckets_path": "jobs>avg_salary"
  22. }
  23. }
  24. }
  25. }
  1. Cumulative_sum示例
  1. #Cumulative_sum 累计求和
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "aggs": {
  6. "age": {
  7. "histogram": {
  8. "field": "age",
  9. "min_doc_count": 0,
  10. "interval": 1
  11. },
  12. "aggs": {
  13. "avg_salary": {
  14. "avg": {
  15. "field": "salary"
  16. }
  17. },
  18. "cumulative_salary":{
  19. "cumulative_sum": {
  20. "buckets_path": "avg_salary"
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }

5 聚合的作用范围

ES聚合分析的默认作用范围是query的查询结果集,同时ES还支持以下方式改变聚合的作用范围:

  • Filter
  • Post Filter
  • Global
  1. #Query
  2. POST employees/_search
  3. {
  4. "size": 0,
  5. "query": {
  6. "range": {
  7. "age": {
  8. "gte": 20
  9. }
  10. }
  11. },
  12. "aggs": {
  13. "jobs": {
  14. "terms": {
  15. "field":"job.keyword"
  16. }
  17. }
  18. }
  19. }
  20. #Filter
  21. POST employees/_search
  22. {
  23. "size": 0,
  24. "aggs": {
  25. "older_person": {
  26. "filter":{
  27. "range":{
  28. "age":{
  29. "from":35
  30. }
  31. }
  32. },
  33. "aggs":{
  34. "jobs":{
  35. "terms": {
  36. "field":"job.keyword"
  37. }
  38. }
  39. }},
  40. "all_jobs": {
  41. "terms": {
  42. "field":"job.keyword"
  43. }
  44. }
  45. }
  46. }
  47. #Post field. 一条语句,找出所有的job类型。还能找到聚合后符合条件的结果
  48. POST employees/_search
  49. {
  50. "aggs": {
  51. "jobs": {
  52. "terms": {
  53. "field": "job.keyword"
  54. }
  55. }
  56. },
  57. "post_filter": {
  58. "match": {
  59. "job.keyword": "Dev Manager"
  60. }
  61. }
  62. }
  63. #global
  64. POST employees/_search
  65. {
  66. "size": 0,
  67. "query": {
  68. "range": {
  69. "age": {
  70. "gte": 40
  71. }
  72. }
  73. },
  74. "aggs": {
  75. "jobs": {
  76. "terms": {
  77. "field":"job.keyword"
  78. }
  79. },
  80. "all":{
  81. "global":{},
  82. "aggs":{
  83. "salary_avg":{
  84. "avg":{
  85. "field":"salary"
  86. }
  87. }
  88. }
  89. }
  90. }
  91. }

6 排序

指定order,按照count和key进行排序:

  • 默认情况,按照count降序排序
  • 指定size,就能返回相应的桶
  1. #排序 order
  2. #count and key
  3. POST employees/_search
  4. {
  5. "size": 0,
  6. "query": {
  7. "range": {
  8. "age": {
  9. "gte": 20
  10. }
  11. }
  12. },
  13. "aggs": {
  14. "jobs": {
  15. "terms": {
  16. "field":"job.keyword",
  17. "order":[
  18. {"_count":"asc"},
  19. {"_key":"desc"}
  20. ]
  21. }
  22. }
  23. }
  24. }
  25. #排序 order
  26. #count and key
  27. POST employees/_search
  28. {
  29. "size": 0,
  30. "aggs": {
  31. "jobs": {
  32. "terms": {
  33. "field":"job.keyword",
  34. "order":[ {
  35. "avg_salary":"desc"
  36. }]
  37. },
  38. "aggs": {
  39. "avg_salary": {
  40. "avg": {
  41. "field":"salary"
  42. }
  43. }
  44. }
  45. }
  46. }
  47. }
  48. #排序 order
  49. #count and key
  50. POST employees/_search
  51. {
  52. "size": 0,
  53. "aggs": {
  54. "jobs": {
  55. "terms": {
  56. "field":"job.keyword",
  57. "order":[ {
  58. "stats_salary.min":"desc"
  59. }]
  60. },
  61. "aggs": {
  62. "stats_salary": {
  63. "stats": {
  64. "field":"salary"
  65. }
  66. }
  67. }
  68. }
  69. }
  70. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/795278
推荐阅读
相关标签
  

闽ICP备14008679号