欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > ElasticSearch - Bucket Script 使用指南

ElasticSearch - Bucket Script 使用指南

2024/11/8 7:38:52 来源:https://blog.csdn.net/yangshangwei/article/details/143327404  浏览:    关键词:ElasticSearch - Bucket Script 使用指南

文章目录

  • 官方文档
  • Bucket Script 官文
  • 1. 什么是 ElasticSearch 中的 Bucket Script?
  • 2. 适用场景
  • 3. Bucket Script 的基本结构
  • 4. 关键参数详解
  • 5. 示例
    • 官方示例:计算每月 T 恤销售额占总销售额的比率百分比
    • 示例计算:点击率 (CTR)
  • 6. 注意事项与限制
  • 7. 最佳实践

在这里插入图片描述


官方文档

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

在这里插入图片描述在这里插入图片描述


Bucket Script 官文

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

在这里插入图片描述在这里插入图片描述
在这里插入图片描述


  1. 介绍 Bucket Script 的概念和作用
  2. 展示基本使用场景,帮助理解其核心原理
  3. 通过实例展示如何实现 Bucket Script
  4. 总结关键要点与最佳实践

1. 什么是 ElasticSearch 中的 Bucket Script?

Bucket Script 是 ElasticSearch 中一种强大的管道聚合(pipeline aggregation),允许你基于已有的聚合结果执行数学计算。 它用于对多个 桶(buckets) 内的数据进行后处理,适合在聚合结果上进行进一步计算,比如计算比率、加权平均等。


2. 适用场景

  • 计算字段的 百分比(如收入增长率)
  • 生成两个字段之间的 比值(如点击率 CTR)
  • 在聚合结果中求得更复杂的 数学表达式
  • 处理基于时间序列的数据分析,例如 同比、环比 增长计算

3. Bucket Script 的基本结构

Bucket Script 聚合的基本结构如下:

{"aggs": {"sales_per_month": {"date_histogram": {"field": "order_date","calendar_interval": "month"},"aggs": {"total_sales": {"sum": {"field": "sales"}},"total_units": {"sum": {"field": "units_sold"}},"sales_per_unit": {"bucket_script": {"buckets_path": {"sales": "total_sales","units": "total_units"},"script": "params.sales / params.units"}}}}}
}
  1. sales_per_month:使用 date_histogram 按月份进行分桶。
  2. total_salestotal_units:分别计算总销售额和总售出单位数。
  3. sales_per_unit:使用 bucket_script 在每个桶内计算销售额与售出单位的比值。

4. 关键参数详解

  • buckets_path:指定需要参与计算的聚合结果路径,路径指向的聚合必须出现在当前或上层的桶中。
  • script:定义计算逻辑,使用 Painless 脚本语言 编写。

5. 示例

官方示例:计算每月 T 恤销售额占总销售额的比率百分比

PUT /sales
{"mappings": {"properties": {"type": {"type": "keyword"},"price": {"type": "float"},"date": {"type": "date"}}}
}POST /sales/_bulk
{ "index": { "_index": "sales" } }
{ "type": "t-shirt", "price": 19.99, "date": "2024-01-05" }
{ "index": { "_index": "sales" } }
{ "type": "t-shirt", "price": 25.50, "date": "2024-01-15" }
{ "index": { "_index": "sales" } }
{ "type": "jeans", "price": 49.99, "date": "2024-01-20" }
{ "index": { "_index": "sales" } }
{ "type": "t-shirt", "price": 15.99, "date": "2024-02-01" }
{ "index": { "_index": "sales" } }
{ "type": "shoes", "price": 75.00, "date": "2024-02-10" }
{ "index": { "_index": "sales" } }
{ "type": "t-shirt", "price": 29.99, "date": "2024-02-15" }POST sales/_searchPOST /sales/_search
{"size": 0,"aggs": {"sales_per_month": {"date_histogram": {"field": "date","calendar_interval": "month"},"aggs": {"total_sales": {"sum": {"field": "price"}},"t-shirts": {"filter": {"term": {"type": "t-shirt"}},"aggs": {"sales": {"sum": {"field": "price"}}}},"t-shirt-percentage": {"bucket_script": {"buckets_path": {"tShirtSales": "t-shirts>sales","totalSales": "total_sales"},"script": "params.tShirtSales / params.totalSales * 100"}}}}}
}

此查询的目的是:

  1. 统计每个月的总销售额
  2. 计算“T-shirt”类型商品的销售额
  3. 计算“T-shirt”销售额占总销售额的百分比

  1. “size”: 0

    • 表示这次查询不返回任何文档,仅返回聚合结果。
  2. 聚合:sales_per_month

    • 使用 date_histogram 来按月对销售数据进行分桶:
      "date_histogram": {"field": "date","calendar_interval": "month"
      }
      
    • 字段 date 决定销售的日期。calendar_interval 设置为 "month",意味着每个月作为一个桶。
  3. 聚合:total_sales

    • 计算每个月的总销售额
      "total_sales": {"sum": {"field": "price"}
      }
      
    • 字段 price 表示商品价格,通过 sum 聚合计算总和。
  4. 过滤聚合:t-shirts

    • 使用 filter 过滤出类型为 t-shirt 的销售:
      "filter": {"term": {"type": "t-shirt"}
      }
      
    • 嵌套的sum聚合 计算T-shirt类型商品的销售额:
      "sales": {"sum": {"field": "price"}
      }
      
  5. 桶脚本聚合:t-shirt-percentage

    • 计算T-shirt销售额占总销售额的百分比
      "bucket_script": {"buckets_path": {"tShirtSales": "t-shirts>sales","totalSales": "total_sales"},"script": "params.tShirtSales / params.totalSales * 100"
      }
      
    • buckets_path 用于从其他聚合中引用路径:
      • "tShirtSales" 引用的是 t-shirts>sales 聚合。
      • "totalSales" 引用的是 total_sales 聚合。
    • script 执行的逻辑是:T-shirt销售额 / 总销售额 * 100,计算百分比。

查询结果格式

{"took" : 6,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 6,"relation" : "eq"},"max_score" : null,"hits" : [ ]},"aggregations" : {"sales_per_month" : {"buckets" : [{"key_as_string" : "2024-01-01T00:00:00.000Z","key" : 1704067200000,"doc_count" : 3,"total_sales" : {"value" : 95.48000144958496},"t-shirts" : {"doc_count" : 2,"sales" : {"value" : 45.489999771118164}},"t-shirt-percentage" : {"value" : 47.64348458366713}},{"key_as_string" : "2024-02-01T00:00:00.000Z","key" : 1706745600000,"doc_count" : 3,"total_sales" : {"value" : 120.97999954223633},"t-shirts" : {"doc_count" : 2,"sales" : {"value" : 45.97999954223633}},"t-shirt-percentage" : {"value" : 38.00628179551602}}]}}
}

这个结果表示:

  • 2024年1月的总销售额为 ** 95.48**。
  • 其中 45.48 元来自于 T-shirt。
  • T-shirt 的销售占比为 ** 47.6%**。


示例计算:点击率 (CTR)

假设有个广告展示量和点击量的聚合,想计算每个广告的点击率:

{"aggs": {"ads": {"terms": {"field": "ad_id"},"aggs": {"impressions": {"sum": {"field": "impression_count"}},"clicks": {"sum": {"field": "click_count"}},"ctr": {"bucket_script": {"buckets_path": {"clicks": "clicks","impressions": "impressions"},"script": "params.clicks / params.impressions"}}}}}
}

逻辑:

  • 使用 terms 聚合按广告 ID 分组
  • 分别计算广告的展示量 (impressions) 和点击量 (clicks)
  • 使用 bucket_script 聚合计算 点击率(CTR) = 点击量 / 展示量

6. 注意事项与限制

  1. 性能影响:由于 Bucket Script 在已有聚合结果上执行计算,处理大量桶时可能会导致性能下降。
  2. 路径依赖buckets_path 必须引用当前层级内或父层级的聚合结果,不能跨层级引用。
  3. 脚本限制:ElasticSearch 默认使用 Painless 脚本, 确保脚本逻辑高效,否则可能导致查询超时。
  4. 溢出处理:注意在脚本中处理除零异常或数据溢出。

7. 最佳实践

  • 数据过滤:提前过滤无关数据,减少参与计算的桶数。
  • 逐步聚合:将复杂计算分解为多个简单的管道聚合,以提高可读性和维护性。
  • 性能调优:如果计算复杂,可以限制返回结果的桶数(例如通过 size 限制 top-N 结果)。

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com