elasticsearch实现聚合后两个字段相除/相加/相减/相乘运算

1、实际需求

在sum聚合运算时会有两个值sum之后相除的运算方式sum(A)/sum(B),这就需要用到es的Bucket Script Aggregation聚合方式。

备注:由于这个问题是一年之前遇到的,现在的新版ES应该有细微变化了,具体的可能需要重测试,但是评论区有人给出了新版的方法,可以尝试一下。

"aggregations" : {
   "A" : {
     "sum" : {
       "field" : "A"
     }
   },
   "B" : {
     "sum" : {
       "field" : "B"
     }
   },
   "(A/B)" : {
     "bucket_script" : {
       "script" : {
         "inline" : "tmpA/tmpB"
       },
       "buckets_path" : {
         "tmpA" : "A",
         "tmpB" : "B"
       }
     }
   }
 }

bucket_path字段是一个映射map,用别名映射A和B聚合的桶,然后再在script中做脚本运算,但是es不支持按照聚合生成字段“(A/B)”排序。

2、Pipeline Aggregations(管道聚合)

sum和bucket_script聚合都是管道聚合(Pipeline)

Pipeline Aggregations 是一组工作在其他聚合计算结果而不是文档集合的聚合。
有很多种不同类型的 Pipeline Aggregations ,不同的 Pipeline Aggregations 对其他聚合计算结果有不同的聚合计算。
总的来说 Pipeline Aggregations 有以下两种类型:

  1. Parent : 以父聚合的结果作为输入,对父聚合的结果进行聚合计算。可以计算出新的桶或是新的聚合结果加入到现有的桶中。
  2. Sibling : 以兄弟聚合(同级聚合)的结果作为输入,对兄弟聚合的结果进行聚合计算。计算出一个新的聚合结果,结果与兄弟聚合的结果同级。

Buckets Path Syntax

Pipeline Aggregations 是针对于其他聚合结果进行聚合计算的聚合,所以需要做到的一点是如何指出需要进行聚合计算的其他聚合。每个 Pipeline Aggregations 都会有一个 bucketspath 参数,用于指定其他聚合。
Pipeline Aggregations 不可以具有子聚合,但是根据类型,可以通过 buckets
path 引用另一个 Pipeline Aggregations ,使管道聚合链接起来。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
要在Java中实现Elasticsearch中两个字段之间的差值取top,您需要使用Elasticsearch的Java客户端库,例如Elasticsearch High Level REST Client。 首先,请确保您已经添加了Elasticsearch Java客户端库的依赖项。如果您使用Maven,请在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.15.0</version> </dependency> ``` 接下来,您可以使用以下Java代码来实现该功能: ```java import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.avg.Avg; import org.elasticsearch.search.builder.SearchSourceBuilder; import java.io.IOException; public class ElasticsearchExample { public static void main(String[] args) { // 创建Elasticsearch客户端 RestHighLevelClient client = new RestHighLevelClient( RestClient.builder("localhost:9200")); // 创建搜索请求 SearchRequest searchRequest = new SearchRequest("your_index"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 设置查询条件 sourceBuilder.query(QueryBuilders.matchAllQuery()); // 设置聚合 sourceBuilder.aggregation( AggregationBuilders.terms("top_difference").field("field1").size(10) .subAggregation(AggregationBuilders.avg("avg_difference") .script("doc['field2'].value - doc['field1'].value")) ); searchRequest.source(sourceBuilder); try { // 执行搜索请求 SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); // 处理聚合结果 Terms termsAgg = searchResponse.getAggregations().get("top_difference"); for (Terms.Bucket bucket : termsAgg.getBuckets()) { String fieldValue = bucket.getKeyAsString(); Avg avgDifference = bucket.getAggregations().get("avg_difference"); double averageDifference = avgDifference.getValue(); System.out.println("Field: " + fieldValue + ", Average Difference: " + averageDifference); } // 关闭Elasticsearch客户端 client.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 在上述代码中,您需要将"localhost:9200"替换为您的Elasticsearch主机和端口。"your_index"应替换为您要执行查询的索引名称。"field1"和"field2"是您要比较的两个字段。 代码中的查询部分使用了`QueryBuilders.matchAllQuery()`来匹配所有文档。您可以根据需要修改查询条件。聚合部分使用`AggregationBuilders`来构建聚合,然后通过循环遍历聚合结果来获取字段值和差值的平均值。 请注意,上述代码仅为示例,您可能需要根据您的实际情况进行适当的修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值