elasticsearch 之 histogram 直方图聚合

news2025/8/8 8:53:21

1. 简介

直方图聚合是一种基于多桶值聚合,可从文档中提取的数值数值范围值来进行聚合。它可以对参与聚合的值来动态的生成固定大小的桶。

2. bucket_key如何计算

假设我们有一个值是32,并且桶的大小是5,那么32四舍五入后变成30,因此文档将落入与键30关联的存储桶中。下面的算式可以精确的确定每个文档的归属桶

bucket_key = Math.floor((value - offset) / interval) * interval + offset

  1. offset:的值默认是从0开始。并且offset的值必须在[0, interval)之间。且需要是一个正数
  2. value:值的参与计算的值,比如某个文档中的价格字段等。

3. 有一组数据,如何确定是落入到那个桶中

此处是我自己的一个理解,如果错误欢迎指出。

存在的数据: [3, 8, 15]
offset = 0
interval = 5

那么可能会分成如下几个桶 [0,5) [5,10) [10, 15) [15,+∞)

  1. 数字3落入的桶 buket_key= Math.floor((3 - 0) / 5) * 5 + 0 = 0,即落入[0,5)这个桶中
  2. 数字8落入的桶 buket_key= Math.floor((8 - 0) / 5) * 5 + 0 = 5,即落入[5,10)这个桶中
  3. 数字15落入的桶 buket_key= Math.floor((15 - 0) / 5) * 5 + 0 = 15,即落入[15,+∞)这个桶中

4、需求

我们有一组api响应时间数据,根据这组数据进行histogram聚合统计

4.1 准备mapping

PUT /index_api_response_time
{
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "api": {
        "type": "keyword"
      },
      "response_time": {
        "type": "integer"
      }
    }
  }
}

此处的mapping比较简单,就3个字段idapiresponse_time

4.2 准备数据

PUT /index_api_response_time/_bulk
{"index":{"_id":1}}
{"api":"/user/infos","response_time": 3}
{"index":{"_id":2}}
{"api":"/user/add"}
{"index":{"_id":3}}
{"api":"/user/update","response_time": 8}
{"index":{"_id":4}}
{"api":"/user/list","response_time": 15}
{"index":{"_id":5}}
{"api":"/user/export","response_time": 30}
{"index":{"_id":6}}
{"api":"/user/detail","response_time": 32}

此处先记录 id=2的数据,这个是没有response_time的,后期聚合时额外处理。

5、histogram聚合操作

5.1、根据response_time聚合,间隔为5

5.1.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,
  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5
      }
    }
  }
}

5.1.2 java代码

@Test
@DisplayName("根据response_time聚合,间隔为5")
public void test01() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .aggregations("agg_01", agg -> agg.histogram(histogram -> histogram.field("response_time")
                    .interval(5D))));
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.1.3 运行结果

运行结果

5.2 在5.1基础上聚合出每个桶总的响应时间

此处聚合一下是为了结合已有的数据,看看每个数据是否落入到了相应的桶中

5.2.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,

  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5
      },
      "aggs": {
        "agg_sum": {
          "sum": {
            "field": "response_time"
          }
        }
      }
    }
  }
}

5.2.2 java代码

@Test
@DisplayName("在test01基础上聚合出每个桶总的响应时间")
public void test02() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .aggregations("agg_01", agg ->
                            agg.histogram(histogram -> histogram.field("response_time").interval(5D))
                               .aggregations("agg_sum", aggSum -> aggSum.sum(sum -> sum.field("response_time")))
                    ));
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.2.3 运行结果

运行结果

5.3 每个桶中必须存在1个文档的结果才返回-min_doc_count

从5.1中的结果我们可以知道,不管桶中是否存在数据,我们都返回了,即返回了很多空桶。 简单理解就是返回的 桶中存在 doc_count=0 的数据,此处我们需要将这个数据不返回

5.3.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,

  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5,
        "min_doc_count": 1
      }
    }
  }
}

5.3.2 java代码

@Test
@DisplayName("每个桶中必须存在1个文档的结果才返回-min_doc_count")
public void test03() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .aggregations("agg_01", agg -> agg.histogram(
                            histogram -> histogram.field("response_time").interval(5D).minDocCount(1)
                            )
                    )
    );
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.3.3 运行结果

运行结果

5.4 补充空桶数据-extended_bounds

这个是什么意思?假设我们通过 response_time >= 10 进行过滤,并且 interval=5 那么es默认情况下就不会返回 bucket_key =0,5,10的桶,那么如果我想返回那么该如何处理呢?可以通过 extended_bounds 来实现
使用extended_bounds时,min_doc_count=0时才有意义。 extended_bounds不会过滤桶。

extended_bound解释

5.4.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,
  "query": {
    "range": {
      "response_time": {
        "gte": 10
      }
    }
  }, 
  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5,
        "min_doc_count": 0,
        "extended_bounds": {
          "min": 0,
          "max": 50
        }
      }
    }
  }
}

5.4.2 java代码

@Test
@DisplayName("补充空桶数据-extended_bounds")
public void test04() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .query(query-> query.range(range -> range.field("response_time").gte(JsonData.of(10))))
                    .aggregations("agg_01", agg -> agg.histogram(
                            histogram -> histogram.field("response_time").interval(5D).minDocCount(0)
                                    .extendedBounds(bounds -> bounds.min(1D).max(50D))
                            )
                    )
    );
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.4.3 运行结果

运行结果

5.5 只展示min-max之间的桶-hard_bounds

只返回min-max之间的桶
此处的数据:

PUT /index_api_response_time/_bulk
{"index":{"_id":1}}
{"api":"/user/infos","response_time": 3}
{"index":{"_id":2}}
{"api":"/user/add"}
{"index":{"_id":3}}
{"api":"/user/update","response_time": 8}
{"index":{"_id":4}}
{"api":"/user/list","response_time": 15}
{"index":{"_id":5}}
{"api":"/user/export","response_time": 25}
{"index":{"_id":6}}
{"api":"/user/detail","response_time": 32}

5.5.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,
  "query": {
    "range": {
      "response_time": {
        "gte": 10
      }
    }
  }, 
  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5,
        "min_doc_count": 0,
        "hard_bounds": {
          "min": 15,
          "max": 25
        }
      },
      "aggs": {
        "a_s": {
          "sum": {
            "field": "response_time"
          }
        }
      }
    }
  }
}

5.5.2 java代码

@Test
@DisplayName("只展示min-max之间的桶-hard_bounds")
public void test05() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .query(query-> query.range(range -> range.field("response_time").gte(JsonData.of(10))))
                    .aggregations("agg_01", agg ->
                            agg.histogram(
                                histogram -> histogram.field("response_time").interval(5D).minDocCount(0)
                                        .hardBounds(bounds -> bounds.min(1D).max(50D))
                            )
                               .aggregations("a_s", sumAgg -> sumAgg.sum(sum -> sum.field("response_time")))
                    )
    );
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.5.3 运行结果

运行结果

5.6 排序-order

By default the returned buckets are sorted by their key ascending, though the order behaviour can be controlled using the order setting. Supports the same order functionality as the Terms Aggregation.

5.6.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,
  "query": {
    "range": {
      "response_time": {
        "gte": 10
      }
    }
  }, 
  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5,
        "order": {
          "_count": "desc"
        }
      }
    }
  }
}

5.6.2 java代码

@Test
@DisplayName("排序order")
public void test06() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .query(query-> query.range(range -> range.field("response_time").gte(JsonData.of(10))))
                    .aggregations("agg_01", agg ->
                            agg.histogram(
                                histogram -> histogram.field("response_time").interval(5D)
                                        .order(NamedValue.of("_count", SortOrder.Desc))
                            )
                    )
    );
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.6.3 运行结果

运行结果

5.7 文档中缺失聚合字段时如何处理-missing

missing value

5.7.1 dsl

GET /index_api_response_time/_search
{
  "size": 0,
  "aggs": {
    "agg_01": {
      "histogram": {
        "field": "response_time",
        "interval": 5,
        "missing": 0
      }
    }
  }
}

5.7.2 java代码

@Test
@DisplayName("文档中缺失聚合字段时如何处理-missing")
public void test07() throws IOException {
    SearchRequest request = SearchRequest.of(search ->
            search
                    .index("index_api_response_time")
                    .size(0)
                    .query(query-> query.range(range -> range.field("response_time").gte(JsonData.of(10))))
                    .aggregations("agg_01", agg ->
                            agg.histogram(
                                histogram -> histogram.field("response_time").interval(5D) .missing(0D)
                            )
                    )
    );
    System.out.println("request: " + request);
    SearchResponse<String> response = client.search(request, String.class);
    System.out.println("response: " + response);
}

5.7.3 运行结果

运行结果

6、完整代码

https://gitee.com/huan1993/spring-cloud-parent/blob/master/es/es8-api/src/main/java/com/huan/es8/aggregations/bucket/HistogramAggs.java

7、参考文档

  1. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-histogram-aggregation.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/34395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

两种方式实现css取消页面鼠标双击选中文字或单击拖动选中文字的效果

问题描述 我们知道浏览器页面上的文字正常情况下我们是可以双击选中、或者单击鼠标横向拖动也能选中的&#xff0c;选中以后可以右击出现面板然后去复制什么的。但是有的时候&#xff0c;这种效果我们并不想要的&#xff0c;比如用户点快了的时候&#xff0c;所以我们需要禁用…

TensorFlow之文本分类算法-3

1 前言 2 收集数据 3 探索数据 4 选择模型 5 准备数据 N-gram向量集 序列向量集 序列向量集主要是用于序列模型中对文本执行分词与向量化&#xff0c;与n-gram向量集类似&#xff0c;也使用特征选择与标准化的技术优化序列向量集的表示。 在一些文本样例中&#xff0c;…

GaussDB-物理、逻辑备份 使用方法和[GAUSS-53403]解决办法

文章目录1.逻辑备份-gs_dump2.逻辑备份恢复数据库3.物理备份&#xff08;分布式集群验证&#xff09;查看物理全量备份集&#xff1a;查看物理增量备份集&#xff1a;查看所有备份集&#xff08;该命令无法确定备份是否有效&#xff09;停止物理备份&#xff1a;使用物理备份集…

centos7安装mysql8.0.31

mysql 官网 https://www.mysql.com/ 找到对应的版本 然后下载 连接虚拟机 mysql 会和 mariadb这个有冲突&#xff0c;需要卸载掉 查看是否有mariadb rpm -qa|grep mariadb rpm -e --nodeps mariadb-libs 这个是强制卸载命令 再查看一下 rpm -qa|grep mariadb 在根目录创建…

2022 APMCM亚太数学建模竞赛 C题 全球是否变暖 问题一python代码实现(更新完毕)

2022 APMCM亚太数学建模竞赛 C题 全球是否变暖 思路及代码实现(持续更新完毕) 更新信息 2022-11-24 10:00 更新问题1和问题2 思路 2022-11-24 23:20 更新问题一代码 2022-11-25 11:00 更新问题二代码 相关链接 【2022 APMCM亚太数学建模竞赛 C题 全球是否变暖 问题一pytho…

高性能数据访问中间件 OBProxy(六):一文讲透数据路由

在《高性能数据访问中间件 OBProxy&#xff08;五&#xff09;&#xff1a;一文讲透数据路由》中&#xff0c;我们讲到了数据路由影响因素包括功能因素、性能因素和高可用因素。本文主要介绍高可用因素相关的内容。 相比传统的 IOE 架构&#xff0c;OceanBase 利用更低的成本实…

【你不知道的javascript上】2. 第三章 全局作用域,函数作用域和块作用域,立即执行函数

预警&#xff1a;【你不知道的javascript】开头的文章&#xff0c;是用来总结书籍《你不知道的Javascript》中我不熟悉的知识&#xff0c;单纯的用来巩固学到的知识&#xff0c;和加深记忆。 可能有些地方我理解的不透彻&#xff0c;所以不能够保证内容的正确性&#xff0c;欢迎…

使用Mysqldump进行定时全备和增备脚本

使用mysqldump进行全备&#xff0c;增备是备份binlog日志 对应的一些变量按照实际环境进行修改即可&#xff0c;如果有更好的思路也可以进行评论交流。 配合计划任务即可完成定时备份的需求&#xff0c;脚本中备份文件存放目录提前创建或者在加个判断进行创建不过我觉得没啥必…

UNIAPP实战项目笔记44 订单页面顶部选项卡 有数据页面样式布局和无数据页面样式布局

UNIAPP实战项目笔记44 订单页面顶部选项卡 有数据页面样式布局和无数据页面样式布局 订单页面顶部选项卡 具体内容图片自己替换哈&#xff0c;随便找了个图片的做示例 具体位置见目录结构 通过 v-show 的false 和 true来切换有无数据页面布局 代码 my-order.vue 页面部分 my-…

[附源码]java毕业设计医院挂号管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

自动化测试定位不到元素怎么办?

1.动态id定位不到元素 分析原因&#xff1a;每次打开页面&#xff0c;ID都会变化。用ID去找元素&#xff0c;每次刷新页面ID都会发生变化。 解决方案&#xff1a;推荐使用xpath的相对路径方法或者cssSelector查找到该元素。 2.iframe原因定位不到元素 分析原因&#xff1a;…

studio3T import a SQL Database to Mongodb(从mysql中导入数据到mongodb)

具体参考studio3T官方文档&#xff1a;Import a SQL Database to MongoDB in 5 Steps | Studio 3T 1、打开SQL Migration-->选择SQL to MongoDB Migration 2、创建源数据库的连接&#xff08;本文源数据库是mysql&#xff09; 3、选择目标数据库 默认选择当前连接的数据库…

【观察】OceanBase社区版4.0:引领时代,更创造时代

今年8月10日&#xff0c;在2022 OceanBase年度发布会上&#xff0c;OceanBase 4.0首次亮相&#xff0c;在经过85天的快速升级迭代&#xff0c;且历经内外部客户的场景测试与真实业务场景的稳定性“打磨”之后&#xff0c;OceanBase 4.0将“简单易用”的应用感受留给了客户。而在…

JS中的setter、getter数据存取器

JS属性可分为两种类型 ① 数据属性    只是简单存储了一个值 ② 存取器属性    最大的特点是在设置、获取属性值的时候能够做一些其他的操作 设置存取器属性的两种方式 ① 直接在对象中设置 let obj {count: 5, // 普通的数据属性// index为存取器属性_index: 1, // _in…

Linux系统上搭建Java的运行环境,并且部署JavaWeb程序

Linux系统上搭建Java的运行环境&#xff0c;并且部署JavaWeb程序 1.JDK 基于yum【包管理器】来进行安装即可。 yum list列出应用商店上所有的软件包名字。 yum list | grep jdk验证安装成功&#xff01;&#xff01; 2.Tomcat 由于yum商店里的tomcat的版本过低&#xff0…

SpringBoot SpringBoot 原理篇 1 自动配置 1.6 bean 的加载方式【四】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.6 bean 的加载方式【四】1.6.1 Import1 自动配置 1.6 bean 的加…

正大数据周五新鲜报 做期货要关注哪块消息?

正规的外盘期货公司都是在香港证监会的监管下&#xff0c;持有合法合规金融牌照。这点好比国内证券和期货公司在中国证监会的监管下一个道理&#xff0c;完全正规合法。 ​ ​如果你是想做主账户往下开展业务&#xff1a; 一、进入香港证监会官网查询该期货公司的编号 二、…

Spring 中 Bean 的作用域和生命周期

目录 1. Bean 的作用域 1.1 Bean 的六大作用域 1.1.1 单例作用域 (singleton) 1.1.2 原型作用域 (prototype) 1.1.3 请求作用域 (request) 1.1.4 会话作用于 (session) 1.1.5 全局作用于 (application) 1.1.6 HTTP WebSocket 作用域 (websocket) 1.2 如何设置 Bean 的…

142.如何个性化推荐系统设计-2

142.1 离线训练 离线训练流程 如何线上实时反馈特征&#xff1f; 在线计算&#xff0c;与曝光日志一起上报&#xff0c;离线直接使用 如何解决曝光不足问题&#xff1f; 使用CTR的贝叶斯平滑&#xff08;CTR 曝光次数 / 点击次数&#xff09; 所有新闻自身CTR服从Beta分布: 某…

199道SpringCloud面试题,你能答上来吗

前言 Spring Cloud Alibaba 是阿里中间件团队主导的一个新生项目&#xff0c;正处于高速迭代中。 其次&#xff0c;对于中国用户来说&#xff0c;Spring Cloud Alibaba 还有一个非常特殊的意义&#xff1a;它将曾经红极一时的 Dubbo&#xff0c;以及阿里巴巴的强力消息中间件…