• ES聚合之Bucket聚合语法讲解


    目录

    目标

    ES版本信息

    官方文档

    实战

    新增测试数据

    基本语法

    先过滤再分桶聚合

    按照范围聚合

    Histogram(直方图/柱状图)

    嵌套分桶聚合

    Date range aggregation(日期范围聚合)

    Filter aggregation

    Filters aggregation

    Missing aggregation

    Multi Terms aggregation(多字段聚合)


    目标

    掌握Bucket aggregations(分桶聚合,相当于MySQL中的分组聚合 )语法,通过本文列举的各种案例举一反三。具体会涉及以下内容:

    • Multi Terms aggregation(多字段聚合);
    • 分桶聚合排序;
    • 分桶聚合前先过滤数据;
    • 根据范围分桶聚合;
    • Histogram(直方图/柱状图);
    • 嵌套分桶聚合;
    • 对日期分桶聚合;
    • 单过滤器和多过滤器;
    • missing聚合。

    ES版本信息

    7.17.5


    官方文档

    Bucket aggregationshttps://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-aggregations-bucket.html


    实战

    新增测试数据

    1. PUT /library_db
    2. {
    3. "settings": {
    4. "index": {
    5. "analysis.analyzer.default.type": "ik_max_word"
    6. }
    7. }
    8. }
    9. PUT /library_db/_bulk
    10. {"index":{"_id":"1"}}
    11. {"id":1,"type":"玄幻","name":"诛仙","words_num":120,"chapter_num":600,"completion_time":"2000-09-01","author":"萧鼎","prices":32.12}
    12. {"index":{"_id":"2"}}
    13. {"id":2,"type":"玄幻","name":"诛仙前传:蛮荒行","words_num":30,"chapter_num":67,"completion_time":"2020-09-01","author":"萧鼎","prices":23.12}
    14. {"index":{"_id":"3"}}
    15. {"id":3,"type":"武侠","name":"天龙八部","words_num":80,"chapter_num":120,"completion_time":"1995-09-01","author":"金庸","prices":52.1}
    16. {"index":{"_id":"4"}}
    17. {"id":4,"type":"武侠","name":"射雕英雄传","words_num":67,"chapter_num":95,"completion_time":"1998-01-01","author":"金庸","prices":4.12}
    18. {"index":{"_id":"5"}}
    19. {"id":5,"type":"武侠","name":"神雕侠侣","words_num":75,"chapter_num":76,"completion_time":"2000-01-01","author":"金庸","prices":32.8}
    20. {"index":{"_id":"6"}}
    21. {"id":5,"type":"武侠","name":"倚天屠龙记","words_num":83,"chapter_num":130,"completion_time":"2003-01-01","author":"金庸","prices":100.12}
    22. {"index":{"_id":"7"}}
    23. {"id":7,"type":"玄幻","name":"凡人修仙传","words_num":600,"chapter_num":3000,"completion_time":"2018-01-01","author":"忘语","prices":120.12}
    24. {"index":{"_id":"8"}}
    25. {"id":8,"type":"玄幻","name":"魔天记","words_num":159,"chapter_num":400,"completion_time":"2019-01-01","author":"忘语","prices":11.12}
    26. {"index":{"_id":"9"}}
    27. {"id":9,"type":"都市异能","name":"黄金瞳","words_num":220,"chapter_num":400,"completion_time":"2019-01-01","author":"打眼","prices":74.5}
    28. {"index":{"_id":"10"}}
    29. {"id":10,"type":"玄幻","name":"将夜","words_num":210,"chapter_num":600,"completion_time":"2014-01-01","author":"血红","prices":32.0}
    30. {"index":{"_id":"11"}}
    31. {"id":11,"type":"军事","name":"亮剑","words_num":120,"chapter_num":100,"completion_time":"2012-01-01","author":"都梁","prices":15.0}

    基本语法

    需求一:求图书馆中每个小说类型的小说数量。

    1. #size=10,表示聚合后展示10条数据。
    2. GET /library_db/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_count": {
    7. "terms": {
    8. "field": "type.keyword",
    9. "size": 10
    10. }
    11. }
    12. }
    13. }

    需求二:求图书馆中每个小说类型的小说数量。按照升序排序。

    1. #同理,降序排序就用desc,这和MySQL是一样的语法。
    2. GET /library_db/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_count": {
    7. "terms": {
    8. "field": "type.keyword",
    9. "size": 10,
    10. "order": {
    11. "_count": "asc"
    12. }
    13. }
    14. }
    15. }
    16. }

    先过滤再分桶聚合

    需求:求图书馆中每个小说类型的小说数量,要求小说字数大于等于100万。

    1. GET /library_db/_search
    2. {
    3. "size": 0,
    4. "query": {
    5. "range": {
    6. "words_num": {
    7. "gte": 100
    8. }
    9. }
    10. },
    11. "aggs": {
    12. "type_count": {
    13. "terms": {
    14. "field": "type.keyword",
    15. "size": 10
    16. }
    17. }
    18. }
    19. }

    按照范围聚合

    需求:求小说字数在0-30万、30万-50万、50万-100万、100万-200万、大于等于200万区间的数量。

    1. GET /library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "words_num_count": {
    6. "range": {
    7. "field": "words_num",
    8. "ranges": [
    9. {
    10. "from": 0,
    11. "to": 30
    12. },
    13. {
    14. "to": 50,
    15. "from": 30
    16. },
    17. {
    18. "to": 100,
    19. "from": 50
    20. },
    21. {
    22. "to": 200,
    23. "from": 100
    24. },
    25. {
    26. "key": ">200",
    27. "from": 200
    28. }
    29. ]
    30. }
    31. }
    32. }
    33. }

    Histogram(直方图/柱状图)

    需求:求图书馆中,各个字数区间的小说数量,每个区间50万字。

    1. #这里会查出来很多空区间。设置min_doc_count=1表示为空区间的数据不返回。
    2. GET /library_db/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_count": {
    7. "histogram": {
    8. "field": "words_num",
    9. "interval": 50,
    10. "min_doc_count": 1
    11. }
    12. }
    13. }
    14. }

    嵌套分桶聚合

    需求:求图书馆中,每种类型的小说的平均价格。

    1. GET /library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "type_group": {
    6. "terms": {
    7. "field": "type.keyword"
    8. },
    9. "aggs": {
    10. "prices_avg": {
    11. "avg": {
    12. "field": "prices"
    13. }
    14. }
    15. }
    16. }
    17. }
    18. }

    Date range aggregation(日期范围聚合)

    分析

    • from和to分别表示开始时间和结束时间;
    • from相当于>=;
    • to相当于<;
    • missing:为缺少的字段设置代替值的作用。

    需求一:求图书馆中,以当前时间后推一年的时间间隔,完本的小说数量。注意:这里按照东八区(北京时间)来计算,所以+8h。

    1. GET /library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "range": {
    6. "date_range": {
    7. "field": "completion_time",
    8. "ranges": [
    9. {
    10. "from": "now+8h-2y/d",
    11. "to": "now+8h-1y/d"
    12. }
    13. ]
    14. }
    15. }
    16. }
    17. }

    需求二:求图书馆中,以2019年为分界线,完本的小说的数据量。没有时间字段,则默认时间字段值为1976-11-30,它们会被划分到Older中。

    1. GET /library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "range": {
    6. "date_range": {
    7. "field": "completion_time",
    8. "missing": "1976-11-30",
    9. "ranges": [
    10. {
    11. "key": "Older",
    12. "to": "2019-01-01"
    13. },
    14. {
    15. "key": "Newer",
    16. "from": "2019-01-01",
    17. "to": "now+8h/d"
    18. }
    19. ]
    20. }
    21. }
    22. }
    23. }

    Filter aggregation

    需求:查询所有小说的平均价格和武侠小说的平均价格。

    1. POST /library_db/_search?size=0&filter_path=aggregations
    2. {
    3. "aggs": {
    4. "avg_price": {
    5. "avg": {
    6. "field": "prices"
    7. }
    8. },
    9. "wx": {
    10. "filter": {
    11. "term": {
    12. "type": "武侠"
    13. }
    14. },
    15. "aggs": {
    16. "wx_avg_prices": {
    17. "avg": {
    18. "field": "prices"
    19. }
    20. }
    21. }
    22. }
    23. }
    24. }
    25. #如果单纯地查询武侠小说的平均价格,query比filter效率更高。
    26. POST /library_db/_search?size=0&filter_path=aggregations
    27. {
    28. "query": { "term": { "type": "武侠" } },
    29. "aggs": {
    30. "wx": { "avg": { "field": "prices" } }
    31. }
    32. }
    33. #不推荐
    34. POST /library_db/_search?size=0&filter_path=aggregations
    35. {
    36. "aggs": {
    37. "wx": {
    38. "filter": { "term": { "type": "武侠" } },
    39. "aggs": {
    40. "wx_avg_prices": { "avg": { "field": "prices" } }
    41. }
    42. }
    43. }
    44. }

    Filters aggregation

    分析

    • 多个过滤条件时,考虑到效率问题,推荐用多过滤器而不是单过滤器。
    • other_bucket_key表示其他,相当于java中的else。

    需求一:查询武侠、玄幻、军事、都市类小说的数量。

    1. GET library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "type_avg": {
    6. "filters": {
    7. "filters": {
    8. "wx": {
    9. "term": {
    10. "type.keyword": "武侠"
    11. }
    12. },
    13. "xh": {
    14. "term": {
    15. "type.keyword": "玄幻"
    16. }
    17. },
    18. "js": {
    19. "term": {
    20. "type.keyword": "军事"
    21. }
    22. },
    23. "ds": {
    24. "term": {
    25. "type.keyword": "都市"
    26. }
    27. }
    28. }
    29. }
    30. }
    31. }
    32. }

    需求二:查询武侠、玄幻、其他类小说的数量。这里的其他类是只除了玄幻和武侠小说的类别。

    1. GET library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "type_avg": {
    6. "filters": {
    7. "filters": {
    8. "wx": {
    9. "term": {
    10. "type.keyword": "武侠"
    11. }
    12. },
    13. "xh": {
    14. "term": {
    15. "type.keyword": "玄幻"
    16. }
    17. }
    18. },
    19. "other_bucket_key": "other_type"
    20. }
    21. }
    22. }
    23. }

    Missing aggregation

    需求:搜索没有价格字段的小说数量。

    1. POST /library_db/_search?size=0
    2. {
    3. "aggs": {
    4. "without_prices": {
    5. "missing": { "field": "prices" }
    6. }
    7. }
    8. }

    Multi Terms aggregation(多字段聚合)

    需求:根据作者和小说类型字段分组,统计小说数量。

    分析:相当于MySQL中对多个字段进行分组。Multi Terms aggregation与terms aggregation相似,但是前者效率低于后者,所以官方文档中建议:如果经常使用的同一组字段,则将这些字段的组合键索引设置为单独的字段并在此字段上使用terms aggregation。

    1. GET /library_db/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "genres_and_products": {
    6. "multi_terms": {
    7. "terms": [{
    8. "field": "type.keyword"
    9. }, {
    10. "field": "author.keyword"
    11. }]
    12. }
    13. }
    14. }
    15. }

  • 相关阅读:
    音视频开发—FFmpeg 从MP4文件中抽取视频H264数据
    Thread常用API
    Python:用一行代码在几秒钟内抓取任何网站
    【Spring Cloud】Eureka注册中心
    阿里云负载均衡SLB,HTTPS动态网站部署负载均衡,实现高并发流量分发
    Thrift RPC添加access log
    Jupyter安装启动、登录密码问题解决
    0022__STM32F103正点原子学习笔记系列——DMA
    LeetCode-1758. 生成交替二进制字符串的最少操作数【字符串,三行代码!】
    微信群发工具,纯Python编写~
  • 原文地址:https://blog.csdn.net/qq_39706570/article/details/126551512