ES 24 - 如何通过Elasticsearch进行聚合检索 (分组统计)

目录

  • 1 普通聚合分析

    • 1.1 直接聚合统计
    • 1.2 先检索, 再聚合
    • 1.3 扩展: fielddata和keyword的聚合比较
  • 2 嵌套聚合
    • 2.1 先分组, 再聚合统计
    • 2.2 先分组, 再统计, 最后排序
    • 2.3 先分组, 组内再分组, 然后统计、排序

1 普通聚合分析

1.1 直接聚合统计

(1) 计算每个tag下的文档数量, 请求语法:

GET book_shop/it_book/_search
{
    "size": 0,              // 不显示命中(hits)的所有文档信息
    "aggs": {
        "group_by_tags": {  // 聚合结果的名称, 需要自定义(复制时请去掉此注释)
            "terms": {
                "field": "tags"
            }
        }
    }
}

(2) 发生错误:

说明: 索引book_shop的mapping映射是ES自动创建的, 它把tag解析成了text类型, 在发起对tag的聚合请求后, 将抛出如下错误:

{
    "error": {
        "root_cause": [
            {
                "type": "illegal_argument_exception",
                "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [tags] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
            }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [......]
    },
    "status": 400
}

(3) 错误分析:

错误信息: Set fielddata=true on [xxxx] ......
错误分析: 默认情况下, Elasticsearch 对 text 类型的字段(field)禁用了 fielddata;
text 类型的字段在创建索引时会进行分词处理, 而聚合操作必须基于字段的原始值进行分析;
所以如果要对 text 类型的字段进行聚合操作, 就需要存储其原始值 —— 创建mapping时指定fielddata=true, 以便通过反转倒排索引(即正排索引)将索引数据加载至内存中.

(4) 解决方案一: 对text类型的字段开启fielddata属性:

  • 将要分组统计的text field(即tags)的fielddata设置为true:

    PUT book_shop/_mapping/it_book
    {
        "properties": {
            "tags": {
                "type": "text",
                "fielddata": true
            }
        }
    }
  • 可参考官方文档进行设置:
    https://www.elastic.co/guide/en/elasticsearch/reference/6.6/fielddata.html. 成功后的结果如下:

    {
      "acknowledged": true
    }
  • 再次统计, 得到的结果如下:
    {
        "took": 153,
        "timed_out": false,
        "_shards": {
            "total": 5,
            "successful": 5,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 4,
            "max_score": 0.0,
            "hits": []
        },
        "aggregations": {
            "group_by_tags": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 6,
                "buckets": [
                    {
                        "key": "java",
                        "doc_count": 3
                    },
                    {
                        "key": "程",
                        "doc_count": 2
                    },
                    ......
                ]
            }
        }
    }

(5) 解决方法二: 使用内置keyword字段:

  • 开启fielddata将占用大量的内存.
  • Elasticsearch 5.x 版本开始支持通过text的内置字段keyword作精确查询、聚合分析:
    GET shop/it_book/_search
    {
        size": 0,
        "aggs": {
            "group_by_tags": {
                "terms": {
                    "field": "tags.keyword"   // 使用text类型的内置keyword字段
              }
          }
        }
    }

1.2 先检索, 再聚合

(1) 统计name中含有“jvm”的图书中每个tag的文档数量, 请求语法:

GET book_shop/it_book/_search
{
    "query": {
        "match": { "name": "jvm" }
    },
    "aggs": {
        "group_by_tags": {  // 聚合结果的名称, 需要自定义. 下面使用内置的keyword字段:
            "terms": { "field": "tags.keyword" }
        }
    }
}

(2) 响应结果:

{
  "took" : 7,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.64072424,
    "hits" : [
      {
        "_index" : "book_shop",
        "_type" : "it_book",
        "_id" : "2",
        "_score" : 0.64072424,
        "_source" : {
          "name" : "深入理解Java虚拟机:JVM高级特性与最佳实践",
          "author" : "周志明",
          "category" : "编程语言",
          "desc" : "Java图书领域公认的经典著作",
          "price" : 79.0,
          "date" : "2013-10-01",
          "publisher" : "机械工业出版社",
          "tags" : [
            "Java",
            "虚拟机",
            "最佳实践"
          ]
        }
      }
    ]
  },
  "aggregations" : {
    "group_by_tags" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Java",
          "doc_count" : 1
        },
        {
          "key" : "最佳实践",
          "doc_count" : 1
        },
        {
          "key" : "虚拟机",
          "doc_count" : 1
        }
      ]
    }
  }
}

1.3 扩展: fielddata和keyword的聚合比较

  • 为某个 text 类型的字段开启fielddata字段后, 聚合分析操作会对这个字段的所有分词分别进行聚合, 获得的结果大多数情况下并不符合我们的需求.
  • 使用keyword内置字段, 不会对相关的分词进行聚合, 结果可能更有用.

推荐使用text类型字段的内置keyword进行聚合操作.

2 嵌套聚合

2.1 先分组, 再聚合统计

(1) 先按tags分组, 再计算每个tag下图书的平均价格, 请求语法:

GET book_shop/it_book/_search
{
    "size": 0,
    "aggs": {
        "group_by_tags": {
            "terms": { "field": "tags.keyword" },
            "aggs": {
                "avg_price": {
                    "avg": { "field": "price" }
                }
            }
        }
    }
}

(2) 响应结果:

  "hits" : {
    "total" : 3,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_tags" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Java",
          "doc_count" : 3,
          "avg_price" : {
            "value" : 102.33333333333333
          }
        },
        {
          "key" : "编程语言",
          "doc_count" : 2,
          "avg_price" : {
            "value" : 114.0
          }
        },
        ......
      ]
    }
  }

2.2 先分组, 再统计, 最后排序

(1) 计算每个tag下图书的平均价格, 再按平均价格降序排序, 查询语法:

GET book_shop/it_book/_search
{
    "size": 0,
    "aggs": {
        "all_tags": {
            "terms": {
                "field": "tags.keyword",
                "order": { "avg_price": "desc" } // 根据下述统计的结果排序
            },
            "aggs": {
                "avg_price": {
                    "avg": { "field": "price" }
                }
            }
        }
    }
}

(2) 响应结果:

与#2.1节内容相似, 区别在于按照价格排序显示了.

2.3 先分组, 组内再分组, 然后统计、排序

(1) 先按价格区间分组, 组内再按tags分组, 计算每个tags组的平均价格, 查询语法:

GET book_shop/it_book/_search
{
    "size": 0,
    "aggs": {
        "group_by_price": {
            "range": {
                "field": "price",
                "ranges": [
                    { "from": 00,  "to": 100 },
                    { "from": 100, "to": 150 }
                ]
            },
            "aggs": {
                "group_by_tags": {
                    "terms": { "field": "tags.keyword" },
                    "aggs": {
                        "avg_price": {
                            "avg": { "field": "price" }
                        }
                    }
                }
            }
        }
    }
}

(2) 响应结果:

  "hits" : {
    "total" : 3,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_price" : {
      "buckets" : [
        {
          "key" : "0.0-100.0",    // 区间0.0-100.0
          "from" : 0.0,
          "to" : 100.0,
          "doc_count" : 1,        // 共查找到了3条文档
          "group_by_tags" : {     // 对tags分组聚合
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Java",
                "doc_count" : 1,
                "avg_price" : {
                  "value" : 79.0
                }
              },
              ......
            ]
          }
        },
        {
          "key" : "100.0-150.0",
          "from" : 100.0,
          "to" : 150.0,
          "doc_count" : 2,
          "group_by_tags" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Java",
                "doc_count" : 2,
                "avg_price" : {
                  "value" : 114.0
                }
              },
              ......
              }
            ]
          }
        }
      ]
    }
  }

版权声明

作者: 马瘦风(https://healchow.com)

出处: 博客园 马瘦风的博客(https://www.cnblogs.com/shoufeng)

感谢阅读, 如果文章有帮助或启发到你, 点个[好文要顶??] 或 [推荐??] 吧??

本文版权归博主所有, 欢迎转载, 但 [必须在文章页面明显位置标明原文链接], 否则博主保留追究相关人员法律责任的权利.

原文地址:https://www.cnblogs.com/shoufeng/p/11290669.html

时间: 2024-07-30 14:22:40

ES 24 - 如何通过Elasticsearch进行聚合检索 (分组统计)的相关文章

ES 12 - 配置使用Elasticsearch的动态映射(dynamic mapping)

目录 1 动态映射(dynamic mapping) 1.1 什么是动态映射 1.2 体验动态映射 1.3 搜索结果不一致的原因分析 2 开启dynamic mapping策略 2.1 约束策略 2.2 策略示例 3 定制dynamic mapping策略 3.1 date_detection - 日期识别策略 3.2 在type中自定义动态映射模板 3.3 [过期]在index中自定义默认映射模板 1 动态映射(dynamic mapping) 1.1 什么是动态映射 动态映射时Elastic

Elasticsearch 之聚合分析入门

本文主要介绍 Elasticsearch 的聚合功能,介绍什么是 Bucket 和 Metric 聚合,以及如何实现嵌套的聚合. 首先来看下聚合(Aggregation): 什么是 Aggregation? 首先举一个生活中的例子,这个是京东的搜索界面,在搜索框中输入"华为"进行搜索,就会得到如上界面,搜索框就是我们常用的搜索功能,而下面这些,比如分类.热点.操作系统.CPU 类型等是根据 ES 的聚合分析获得的相关结果. 看完上面这个例子,下面来看下聚合的定义: ES 除了搜索以外,

用 mongodb + elasticsearch 实现中文检索

而 elasticsearch 可以很好的支持各种语言的全文检索,但我们暂时又不想切换到 elasticsearch 作为后端数据库. 当然,可以在 web 应用中存储数据的时候,再主动写一份到 elasticsearch,但这无疑污染了原有的业务逻辑. 在 IT 行业,只要有需求的地方,必然早已有了一堆好用或者不好用的开源轮子. 幸运地是,现在已经有了一些转换方案,可以将 mongodb 中的数据自动导入到 elasticsearch 中,让 elasticsearch 提供中文智能检索. 转

ES(一)——Windows安装ElasticSearch

一.安装JDK环境与环境变量配置 因为ElasticSearch是用Java语言编写的,所以必须安装JDK的环境,并且是JDK 1.8以上,具体操作步骤自行百度 安装完查看java版本      注意:最好还是安装jdk11或者以上的,我jdk8安装后面报错 java -version 二.官网下载最新版本ElasticSearch 下载地址:https://www.elastic.co/cn/downloads/elasticsearch,选择相应版本下载即可 三.下载其他版本 直接点击:ht

Python 数据分析(二 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识

Python 数据分析(二) 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识 第1节 groupby 技术 第2节 数据聚合 第3节 分组级运算和转换 第4节 透视表和交叉表 第5节 时间序列 第6节 日期的规范.频率以及移动 第7节 时区处理 第8节 时期及算术运算 第9节 重采样及频率转换 第10节 时间序列绘图 groupby 技术 一.实验简介 Python 数据分析(二)需要同学们先行学完 Python 数据分析(一)的课程. 对数据集进行分

14.SQL语句[6] 聚合、分组

--======================聚合函数============================ --求和sum 求平均avg 求个数count 最大值max 最小值min select sum(金额) as 总金额, avg(金额) as 平均金额, max(金额) as 最大金额, min(金额) as 最小金额, COUNT(*) as 订单数 from 数据 --为什么运行时报错? select 商品,SUM(金额) as 总金额 from 数据 --聚合之后的1个结果,

《利用python进行数据分析》读书笔记--第九章 数据聚合与分组运算

对数据进行分组并对各组应用一个函数,是数据分析的重要环节.数据准备好之后,通常的任务就是计算分组统计或生成透视表.groupby函数能高效处理数据,对数据进行切片.切块.摘要等操作.可以看出这跟SQL关系密切,但是可用的函数有很多.在本章中,可以学到: 根据一个或多个键(可以是函数.数组或DataFrame列名)拆分pandas对象 计算分组摘要统计,如计数.平均值.标准差.,或自定义函数 对DataFrame的列应用各种各样的函数 应用组内转换或其他运算,如规格化.线性回归.排名或选取子集等

Python数据聚合和分组运算(1)-GroupBy Mechanics

前言 Python的pandas包提供的数据聚合与分组运算功能很强大,也很灵活.<Python for Data Analysis>这本书第9章详细的介绍了这方面的用法,但是有些细节不常用就容易忘记,遂打算把书中这部分内容总结在博客里,以便复习查看.根据书中的章节,这部分知识包括以下四部分: 1.GroupBy Mechanics(groupby技术) 2.Data Aggregation(数据聚合) 3.Group-wise Operation and Transformation(分组级运

运维 2.0 时代:数据聚合和分组

运维 2.0 时代:数据聚合和分组 from http://www.cnblogs.com/oneapm/p/4962111.html 运维 2.0 是指,从技术运维升级为服务运维,向公司提供可依赖的专业服务.运维 2.0 强调服务交付能力,而不是技术能力,需求可依赖.懂业务.服务化的专业运维. 为了了解运维 2.0 时代的监控方式,我们不妨从以前的监控手段说起.首先来了解一下 Zabbix ,通过 Zabbix 能够监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员