• Elasticsearch学习-- 聚合查询


    一、聚合分类

     1. 分桶聚合  bucket aggregations

    按照每个标签进行分类 ,类似于group by

     

     

     

     2. 指标聚合 metrics aggregations

     

    3. 管道聚合 pipeline aggregations

    先计算平均值,再计算最小值

     

     二、语法

    1. GET test_index/_search
    2. {
    3. "aggs": {
    4. "聚合后返回的字段": {
    5. "avg": {
    6. "聚合的字段": ""
    7. }
    8. },
    9. "聚合后返回的字段2": {
    10. "avg": {
    11. "聚合的字段": ""
    12. }
    13. }
    14. }
    15. }

     默认查询返回结果是10条,可以通过设置size来看返回值数量

    GET test_index/_search?size=20
    1. GET test_index/_search
    2. {
    3. "size":20
    4. }

    三、桶聚合

    1. 统计不同标签的商品数量

    1. PUT product/_doc/1
    2. {
    3. "name":"prodect1 aa",
    4. "price": 1000,
    5. "tags":["tag1","tag2","tag3"]
    6. }
    7. PUT product/_doc/2
    8. {
    9. "name":"prodect2 bb",
    10. "price": 2000,
    11. "tags":["tag2","tag3"]
    12. }
    13. PUT product/_doc/3
    14. {
    15. "name":"prodect3 bb",
    16. "price": 2000,
    17. "tags":["tag4"]
    18. }
    19. PUT product/_doc/4
    20. {
    21. "name":"prodect4 bb",
    22. "price": 3000,
    23. "tags":["tag1","tag4"]
    24. }
    25. PUT product/_doc/5
    26. {
    27. "name":"prodect5 aa",
    28. "price": 3000,
    29. "tags":["tag1","tag5"]
    30. }
    31. PUT product/_doc/6
    32. {
    33. "name":"prodect6 aa",
    34. "price": 4000,
    35. "tags":["tag1","tag2"]
    36. }
    37. GET product/_search
    38. {
    39. "size": 0,
    40. "aggs": {
    41. "agg_tag": {
    42. "terms": {
    43. "field": "tags.keyword",
    44. "size": 10,
    45. "order": {
    46. "_count": "asc"
    47. }
    48. }
    49. }
    50. }
    51. }

     

    2. 为什么上面使用tags.keyword

    因为聚合查询使用的是doc_values的正排索引,tags.keyword有正排索引

    也可以通过设置fileddata属性进行正排索引

    3. fileddata

    修改mapping中tags字段的fileddata属性为true

    1. POST product/_mapping
    2. {
    3. "properties":{
    4. "tags":{
    5. "type":"text",
    6. "fielddata":true
    7. }
    8. }
    9. }

    这样就可以使用tags直接进行聚合操作

    1. GET product/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "agg_tag": {
    6. "terms": {
    7. "field": "tags",
    8. "size": 10,
    9. "order": {
    10. "_count": "asc"
    11. }
    12. }
    13. }
    14. }
    15. }

    4. doc_values和field_data的区别

    doc_values和filed_data都可以用于聚合查询,

    doc_vaules是基于磁盘的,filed_data是基于内存的

    数据量比较大时,尽量不要使用filed_data

    四、指标聚合

    1. 统计商品最贵、最便宜、平均价格

    1. GET product/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "max_price": {
    6. "max": {
    7. "field": "price"
    8. }
    9. },
    10. "min_price": {
    11. "min": {
    12. "field": "price"
    13. }
    14. },
    15. "avg_price": {
    16. "avg": {
    17. "field": "price"
    18. }
    19. }
    20. }
    21. }

     

     2. stats 查看所有指标

    1. # 查看price的所有指标
    2. GET product/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "stats_price": {
    7. "stats": {
    8. "field": "price"
    9. }
    10. }
    11. }
    12. }

     3. cardinality去重后的数量

    1. # 按照price字段进行去重后的数量
    2. GET product/_search
    3. {
    4. "_source": false,
    5. "aggs": {
    6. "price_count": {
    7. "cardinality": {
    8. "field": "price"
    9. }
    10. }
    11. }
    12. }

     五、管道聚合(二次聚合)

    统计平均价格最低的商品分类

    1)先对tags进行分桶

    2)对分桶后的tags取平均price(在哪个的基础上进行操作,就放在同一级)

    3)对上面的平均价格取最小平均价格的标签

    1. # 统计平均价格最低的商品分类
    2. GET product/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "tags_bucket": {
    7. "terms": {
    8. "field": "tags.keyword"
    9. },
    10. "aggs":{
    11. "avg_price_bucket":{
    12. "avg": {
    13. "field": "price"
    14. }
    15. }
    16. }
    17. },
    18. "min_price_bucket":{
    19. "min_bucket": {
    20. "buckets_path": "tags_bucket>avg_price_bucket"
    21. }
    22. }
    23. }
    24. }

     六、基于聚合结果的聚合--案例

    1. 准备数据

    11条商品信息

    1. PUT /goods/_doc/1
    2. {
    3. "name" : "小米手机",
    4. "desc" : "手机中的战斗机",
    5. "price" : 3999,
    6. "lv":"旗舰机",
    7. "type":"手机",
    8. "createtime":"2020-10-01T08:00:00Z",
    9. "tags": [ "性价比", "发烧", "不卡顿" ]
    10. }
    11. PUT /goods/_doc/2
    12. {
    13. "name" : "小米NFC手机",
    14. "desc" : "支持全功能NFC,手机中的滑翔机",
    15. "price" : 4999,
    16. "lv":"旗舰机",
    17. "type":"手机",
    18. "createtime":"2020-05-21T08:00:00Z",
    19. "tags": [ "性价比", "发烧", "公交卡" ]
    20. }
    21. PUT /goods/_doc/3
    22. {
    23. "name" : "NFC手机",
    24. "desc" : "手机中的轰炸机",
    25. "price" : 2999,
    26. "lv":"高端机",
    27. "type":"手机",
    28. "createtime":"2020-06-20",
    29. "tags": [ "性价比", "快充", "门禁卡" ]
    30. }
    31. PUT /goods/_doc/4
    32. {
    33. "name" : "小米耳机",
    34. "desc" : "耳机中的黄焖鸡",
    35. "price" : 999,
    36. "lv":"百元机",
    37. "type":"耳机",
    38. "createtime":"2020-06-23",
    39. "tags": [ "降噪", "防水", "蓝牙" ]
    40. }
    41. PUT /goods/_doc/5
    42. {
    43. "name" : "红米耳机",
    44. "desc" : "耳机中的肯德基",
    45. "price" : 399,
    46. "type":"耳机",
    47. "lv":"百元机",
    48. "createtime":"2020-07-20",
    49. "tags": [ "防火", "低音炮", "听声辨位" ]
    50. }
    51. PUT /goods/_doc/6
    52. {
    53. "name" : "小米手机10",
    54. "desc" : "充电贼快掉电更快,超级无敌望远镜,高刷电竞屏",
    55. "price" : "",
    56. "lv":"旗舰机",
    57. "type":"手机",
    58. "createtime":"2020-07-27",
    59. "tags": [ "120HZ刷新率", "120W快充", "120倍变焦" ]
    60. }
    61. PUT /goods/_doc/7
    62. {
    63. "name" : "挨炮 SE2",
    64. "desc" : "除了CPU,一无是处",
    65. "price" : "3299",
    66. "lv":"旗舰机",
    67. "type":"手机",
    68. "createtime":"2020-07-21",
    69. "tags": [ "割韭菜", "割韭菜", "割新韭菜" ]
    70. }
    71. PUT /goods/_doc/8
    72. {
    73. "name" : "XS Max",
    74. "desc" : "听说要出新款12手机了,终于可以换掉手中的4S了",
    75. "price" : 4399,
    76. "lv":"旗舰机",
    77. "type":"手机",
    78. "createtime":"2020-08-19",
    79. "tags": [ "5V1A", "4G全网通", "大" ]
    80. }
    81. PUT /goods/_doc/9
    82. {
    83. "name" : "小米电视",
    84. "desc" : "70寸性价比只选,不要一万八,要不要八千八,只要两千九百九十八",
    85. "price" : 2998,
    86. "lv":"高端机",
    87. "type":"耳机",
    88. "createtime":"2020-08-16",
    89. "tags": [ "巨馍", "家庭影院", "游戏" ]
    90. }
    91. PUT /goods/_doc/10
    92. {
    93. "name" : "红米电视",
    94. "desc" : "我比上边那个更划算,我也2998,我也70寸,但是我更好看",
    95. "price" : 2999,
    96. "type":"电视",
    97. "lv":"高端机",
    98. "createtime":"2020-08-28",
    99. "tags": [ "大片", "蓝光8K", "超薄" ]
    100. }
    101. PUT /goods/_doc/11
    102. {
    103. "name": "红米电视",
    104. "desc": "我比上边那个更划算,我也2998,我也70寸,但是我更好看",
    105. "price": 2998,
    106. "type": "电视",
    107. "lv": "高端机",
    108. "createtime": "2020-08-28",
    109. "tags": [
    110. "大片",
    111. "蓝光8K",
    112. "超薄"
    113. ]
    114. }

    2. 统计不同lv下的不同type的数量

    1. # 统计不同lv下的不同type的数量
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "lv_type_agg": {
    7. "terms": {
    8. "field": "lv.keyword"
    9. },
    10. "aggs": {
    11. "type_agg": {
    12. "terms": {
    13. "field": "type.keyword"
    14. }
    15. }
    16. }
    17. }
    18. }
    19. }

      

    3. 统计不同lv的价格信息

    1. # 统计不同lv下价格信息
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "lv_type_agg": {
    7. "terms": {
    8. "field": "lv.keyword"
    9. },
    10. "aggs": {
    11. "price_agg": {
    12. "stats": {
    13. "field": "price"
    14. }
    15. }
    16. }
    17. }
    18. }
    19. }

     4. 统计不同type下的,不同lv的,price信息

    1. #统计不同type下的,不同lv的,price信息
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_agg": {
    7. "terms": {
    8. "field": "type.keyword"
    9. },
    10. "aggs": {
    11. "lv_agg": {
    12. "terms": {
    13. "field": "lv.keyword"
    14. },
    15. "aggs": {
    16. "price_agg": {
    17. "stats": {
    18. "field": "price"
    19. }
    20. }
    21. }
    22. }
    23. }
    24. }
    25. }
    26. }

     统计不同type下的,不同lv的,price信息和tag信息

    1. #统计不同type下的,不同lv的,price信息和tag信息
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_agg": {
    7. "terms": {
    8. "field": "type.keyword"
    9. },
    10. "aggs": {
    11. "lv_agg": {
    12. "terms": {
    13. "field": "lv.keyword"
    14. },
    15. "aggs": {
    16. "price_agg": {
    17. "stats": {
    18. "field": "price"
    19. }
    20. },
    21. "tag_agg": {
    22. "terms": {
    23. "field": "tags.keyword"
    24. }
    25. }
    26. }
    27. }
    28. }
    29. }
    30. }
    31. }

     

     

    5. 统计每个商品type中,不同的lv商品中,平均price最低的lv

    1. # 统计每个商品type中,不同的lv商品中,平均price最低的lv
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_agg": {
    7. "terms": {
    8. "field": "type.keyword"
    9. },
    10. "aggs": {
    11. "lv_agg": {
    12. "terms": {
    13. "field": "lv.keyword"
    14. },
    15. "aggs": {
    16. "price_agg": {
    17. "avg": {
    18. "field": "price"
    19. }
    20. }
    21. }
    22. },
    23. "min_price_bucket": {
    24. "min_bucket": {
    25. "buckets_path": "lv_agg>price_agg"
    26. }
    27. }
    28. }
    29. }
    30. }
    31. }

     七、基于查询结果的聚合和基于聚合结果的查询--案例

    1. 基于查询结果的聚合

    1)查询price>4000的tags信息

    1. GET goods/_search
    2. {
    3. "size": 10,
    4. "query": {
    5. "range": {
    6. "price": {
    7. "gte": 4000
    8. }
    9. }
    10. },
    11. "aggs": {
    12. "tags_bucket": {
    13. "terms": {
    14. "field": "tags.keyword"
    15. }
    16. }
    17. }
    18. }

     2) 基于filter

    与上面的结果一样

    1. GET goods/_search
    2. {
    3. "size": 10,
    4. "query": {
    5. "constant_score": {
    6. "filter": {
    7. "range": {
    8. "price": {
    9. "gte": 4000
    10. }
    11. }
    12. }
    13. }
    14. },
    15. "aggs": {
    16. "tags_bucket": {
    17. "terms": {
    18. "field": "tags.keyword"
    19. }
    20. }
    21. }
    22. }

    2. 基于聚合结果的查询

    使用post_filter

    1. GET goods/_search
    2. {
    3. "size": 10,
    4. "aggs": {
    5. "tags_bucket": {
    6. "terms": {
    7. "field": "tags.keyword"
    8. }
    9. }
    10. },
    11. "post_filter": {
    12. "term": {
    13. "tags.keyword": "性价比"
    14. }
    15. }
    16. }
    1. GET goods/_search
    2. {
    3. "size": 10,
    4. "query": {
    5. "term": {
    6. "tags.keyword": {
    7. "value": "性价比"
    8. }
    9. }
    10. },
    11. "aggs": {
    12. "tags_bucket": {
    13. "terms": {
    14. "field": "tags.keyword"
    15. }
    16. }
    17. }
    18. }

    以上两个语句,查询结果相同

    1)查询price>4000的平均price和所有商品的平均price

    1. #查询price>4000的平均price和所有商品的平均price
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "query": {
    6. "range": {
    7. "price": {
    8. "gte": 4000
    9. }
    10. }
    11. },
    12. "aggs": {
    13. "avg_price": {
    14. "avg": {
    15. "field": "price"
    16. }
    17. },
    18. "all_avg_price":{
    19. "global": {},
    20. "aggs":{
    21. "avg_price2":{
    22. "avg": {
    23. "field": "price"
    24. }
    25. }
    26. }
    27. }
    28. }
    29. }

     2) 将上面的global换成filter的话,是与最上面的查询条件产生交集

    1. GET goods/_search
    2. {
    3. "size": 0,
    4. "query": {
    5. "range": {
    6. "price": {
    7. "gte": 4000
    8. }
    9. }
    10. },
    11. "aggs": {
    12. "avg_price": {
    13. "avg": {
    14. "field": "price"
    15. }
    16. },
    17. "all_avg_price":{
    18. "filter": {
    19. "range": {
    20. "price": {
    21. "lte": 3000
    22. }
    23. }
    24. },
    25. "aggs":{
    26. "avg_price2":{
    27. "avg": {
    28. "field": "price"
    29. }
    30. }
    31. }
    32. }
    33. }
    34. }

     八、聚合排序

    1. _count

    按照doc_count排序

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

     

    2._term/_key

    _term已经淘汰,按照key字典序排序

    1. GET goods/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "tags_aggs": {
    6. "terms": {
    7. "field": "tags.keyword",
    8. "order": {
    9. "_key": "asc"
    10. }
    11. }
    12. }
    13. }
    14. }

     

    3. 多层聚合

    外层按照type的数量倒序排,里层按照lv的数量正序排

    1. GET goods/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "type_aggs": {
    6. "terms": {
    7. "field": "type.keyword",
    8. "order": {
    9. "_count": "desc"
    10. }
    11. },
    12. "aggs": {
    13. "lv_aggs": {
    14. "terms": {
    15. "field": "lv.keyword",
    16. "order": {
    17. "_count": "asc"
    18. }
    19. }
    20. }
    21. }
    22. }
    23. }
    24. }

     

     根据price_stats中的最小值进行排序

    1. # 根据price_stats中的最小值进行排序
    2. GET goods/_search
    3. {
    4. "size": 0,
    5. "aggs": {
    6. "type_aggs": {
    7. "terms": {
    8. "field": "type.keyword",
    9. "order": {
    10. "filter_aggs>price_stats.min": "asc"
    11. }
    12. },
    13. "aggs": {
    14. "filter_aggs": {
    15. "filter": {
    16. "terms": {
    17. "type.keyword": [
    18. "耳机",
    19. "手机",
    20. "电视"
    21. ]
    22. }
    23. },
    24. "aggs": {
    25. "price_stats": {
    26. "stats": {
    27. "field": "price"
    28. }
    29. }
    30. }
    31. }
    32. }
    33. }
    34. }
    35. }

     九、图形化

    1. 根据价格range分桶

    1. GET goods/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "price_range": {
    6. "range": {
    7. "field": "price",
    8. "ranges": [
    9. {
    10. "from": 0,
    11. "to": 1000
    12. },
    13. {
    14. "from": 1000,
    15. "to": 2000
    16. },
    17. {
    18. "from": 2000,
    19. "to": 3000
    20. },
    21. {
    22. "from": 3000,
    23. "to": 4000
    24. },
    25. {
    26. "from": 4000,
    27. "to": 5000
    28. }
    29. ]
    30. }
    31. }
    32. }
    33. }

     2. histogram(直方图、柱状图)

    根据price,间隔1000,跟上面的基本相同

    1. GET goods/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "price_range": {
    6. "histogram": {
    7. "field": "price",
    8. "interval": 1000
    9. }
    10. }
    11. }
    12. }

    跟field、interval同级的其他参数

    keyed:设置true,表示将结果输出为key、value形式

    min_doc_count:设置成1,表示输出结果doc_value大于等于1的数据(过滤0)

    missing:对空值赋默认值(设置成500,上图中表示,将price缺失的数据的price设置成500)

    3. date-histogram

    专门针对日期类型的直方图

    根据月份进行分桶,可以用format进行指定格式输出

    1. GET goods/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "date_range": {
    6. "date_histogram": {
    7. "field": "createtime",
    8. "interval": "month"
    9. }
    10. }
    11. }
    12. }

     可以设置extended_bounds,展示没有的数据0

     4. auto_date_histogram

    自动设置interval,根据buckets

    5. cumulative_sum(累加聚合)

     十、percentile (百分位统计、饼状图)

    1. percentiles

     2. percentile_ranks

     

  • 相关阅读:
    Dapper迁移SqlSugar问题汇总
    Allegro输出带等长规则的Excel操作指导
    实现文档AI搜索,提高问题解决效率
    「UI开发」DevExpress WPF Pivot Grid组件可轻松实现多维数据分析!(一)
    Docker安装Elasticsearch 8.x 、Kibana 8.x等
    LabVIEW中的数据通信方法
    3D 纹理渲染如何帮助设计师有效、清晰地表达设计理念
    MyBatis的二级缓存
    fastadmin/thinkPHPQueue消息队列详细教程
    Python + re + scrapy.Selector: 分析提取某在线征信站体系内容(一)
  • 原文地址:https://blog.csdn.net/CelineT/article/details/126570118