elastic:nested实现对满足条件的数组元素聚合查询

0. 引言

某些业务场景下,我们要对数组元素进行聚合查询,就需要用到nested数据类型,但部分场景是针对数组中指定的元素进行聚合,于是就需要对数组元素进行限定,今天来看看这种场景如何实现。

1. 数据准备

首先我们准备一下模拟数据:一个订单下有各个商品,我们需要统计销售额前3的生鲜商品

mapping如下:

PUT orders 
{"settings": {"number_of_replicas": 0,"number_of_shards": 1},"mappings": {"properties": {"order_no": {"type": "keyword"},"create_user": {"type": "keyword"},"product_list":{"type": "nested","properties": {"name": {"type": "keyword"},"number": {"type": "integer"},"type": {"type": "keyword"}}}}}
}

提供点模拟数据,供大家演练

POST orders/_bulk 
{"index":{}}
{"order_no":"1","create_user":"张三","product_list":[{"name":"苹果", "number":2, "type":"生鲜"},{"name":"水壶", "number":2, "type":"百货"},{"name":"香蕉", "number":4, "type":"生鲜"}]}
{"index":{}}
{"order_no":"2","create_user":"李四","product_list":[{"name":"榴莲", "number":1, "type":"生鲜"},{"name":"小米手机", "number":2, "type":"百货"},{"name":"鲫鱼", "number":5, "type":"生鲜"}]}
{"index":{}}
{"order_no":"2","create_user":"周吴","product_list":[{"name":"苹果", "number":4, "type":"生鲜"},{"name":"香梨", "number":2, "type":"生鲜"},{"name":"毛巾", "number":4, "type":"百货"}]}

2. 实现

以下实现基于elasticsearch 7.13.0版本

1、我们来看直接查询的情况

GET orders/_search
{"size": 0,"aggs": {"product_agg": {"nested": {"path": "product_list"},"aggs": {"name_agg": {"terms": {"field": "product_list.name"},"aggs": {"number_sum": {"sum": {"field": "product_list.number"}},"sort": {"bucket_sort": {"sort": [{"number_sum.value": {"order": "desc"}}],"size": 3}}}}}}}
}

不做商品类型筛选的话,可以看到我们通过nested聚合来实现统计,通过bucket_sort来实现排序,同时再用size参数限定下前3输出,即可实现我们的需求。

  • nested agg官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-bucket-nested-aggregation.html

  • bucket sort官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-pipeline-bucket-sort-aggregation.html

在这里插入图片描述

但是从输出结果很明显的看出,这不是我们想要的结果,我们需要对数组内的type属性做一下筛选,只需要“生鲜”商品

而实现上es中提供了filter参数供我们来筛选聚合元素,我们可以利用它来实现聚合条件的筛选,如下,在官方文档中的filter用法如下:

  • filter agg 官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-bucket-filter-aggregation.html
    在这里插入图片描述

这里需要注意的是,要把嵌套的聚合新写一个agg然后放到filter同级下,也就是作为filter的子聚合;即将filter聚合的结果,作为下一次聚合的入参

GET orders/_search
{"size": 0,"aggs": {"product_agg": {"nested": {"path": "product_list"},"aggs": {"type_filter": {"filter": {"term": {"product_list.type": "生鲜"}},"aggs": {"name_agg": {"terms": {"field": "product_list.name"},"aggs": {"number_sum": {"sum": {"field": "product_list.number"}},"sort": {"bucket_sort": {"sort": [{"number_sum.value": {"order": "desc"}}],"size": 3}}}}}}}}}
}

执行出来的结果如下,符合预期
在这里插入图片描述

另外再附加上java client的实现代码,供大家参考,这里使用了RestHighLevelClient作为客户端

 @Resource
private RestHighLevelClient restClient;public void test() throws IOException {String outAggName = "product_agg";String filterAggName = "type_filter";String termAggName = "name_agg";TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termAggName).field("product_list.name");SearchSourceBuilder searchBuilder = new SearchSourceBuilder();searchBuilder.aggregation(AggregationBuilders.nested(outAggName, "product_list").subAggregation(AggregationBuilders.filter(filterAggName, new TermQueryBuilder("product_list.type", "生鲜")).subAggregation(termsAggregationBuilder.subAggregation(AggregationBuilders.sum("number_sum").field("product_list.number")).order(BucketOrder.aggregation("number_sum.value", false)))));searchBuilder.size(0);SearchRequest searchRequest = new SearchRequest("orders");searchRequest.source(searchBuilder);SearchResponse response = restClient.search(searchRequest, RequestOptions.DEFAULT);Map<String, Aggregation> resultMap = response.getAggregations().getAsMap();ParsedNested aggResults = (ParsedNested) resultMap.get(outAggName);ParsedFilter filterAgg = aggResults.getAggregations().get(filterAggName);ParsedStringTerms termAgg = filterAgg.getAggregations().get(termAggName);List<? extends Terms.Bucket> buckets = termAgg.getBuckets();for (Terms.Bucket bucket : buckets) {// TODO 获取分组结果}}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flask搞个简单登录界面

登录界面 直接放上login.html模板&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Lo…

Git总结 | Git面试都问些啥?

什么是Git为什么要用Git等等这些相信看到该标题点进来的同学也不希望浪费时间再看一遍&#xff0c;那么直接进入主题&#xff0c;对于日常工作中常用的Git相关操作进行整理&#xff0c;一起看看吧 面试官&#xff1a;你常用的Git操作是什么? 候选人&#xff1a;git clone 面试…

2024年手把手教CleanMyMac X v4.14.6破解版安装激活图文教程

小编给您带来CleanMyMac X v4.14.6中文破解版&#xff0c;CleanMyMac X破解版是应用在MacOS上的一款Mac系统清理优化工具&#xff0c;使用cleanmymac x 中文破解版只需两个简单步骤就可以把系统里那些乱七八糟的无用文件统统清理掉&#xff0c;节省宝贵的磁盘空间。 CleanMyMac…

LeetCode(62)删除排序链表中的重复元素 II【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 删除排序链表中的重复元素 II 1.题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1…

「Verilog学习笔记」流水线乘法器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule multi_pipe#(parameter size 4 )(input clk , input rst_n ,input [size-1:0] mul_a ,input [size-1:0] mul_b ,output …

鞋帽箱包品牌网站作用如何

鞋帽箱包是市场中很常见的产品&#xff0c;同时需求度又很高&#xff0c;是人们生活所需&#xff0c;除了个别高端品牌外&#xff0c;其它多数产品价格一般都比较低&#xff0c;因此很少有人会在意品牌&#xff0c;只要质量、价格、舒适度、美观好即可。 然而对企业来讲&#…

git图形化使用

Eclipse中是在工作空间中创建一个项目。 idea中是一个窗口算是一个项目。 Android studio中也是一个窗口算一个项目&#xff0c;不一样的是项目的每一个模块都可以作为一个app运行。 使用可视化界面来使用git&#xff1a; 使用Git的步骤&#xff1a; 首先下载客户端Gitkrak…

利用原始套接字解决mac地址错误问题【南瑞SysKeeper-2000】

一&#xff1a;案例描述 一键可视顺控图像智能项目在网络部署过程中&#xff0c;对网络限制隔离安全性要求很高&#xff0c;用到正向隔离装置&#xff08;南瑞SysKeeper-2000型号&#xff09;。 图一 正向装置示意图 现场发现问题&#xff1a;直连网线情况下&#xff0c;我方…

深度剖析JavaScript中冒泡和捕获机制、事件代理

JS事件传播的两种机制包括冒泡和捕获&#xff0c;下面将具体剖析它们之间本质的区别。 事件冒泡: 先触发子元素的事件&#xff0c;再触发父元素的事件。 创建一个 ul label 和 li label, 分别绑定一个父id 和 子 id, 再通过创建 script&#xff0c;去绑定各自的点击事件。 <…

如何提高股票交易速度?极速交易哪家好?

极速交易模式是一种交易方式&#xff0c;它以最短的时间进行快速交易。这种模式通常用于贵金属、外汇、原油、期权等金融产品的交易。 在极速交易模式中&#xff0c;交易者可以在最短时间内进行买卖操作&#xff0c;从而快速获取利润。这种交易方式通常需要高超的技术和经验&a…

如何免费搭建私人电影网站(一)

前言&#xff1a;在线看电影经常会出现烦人的广告&#xff0c;为了不浪费时间看广告&#xff0c;有必要做自己的专属网站。 准备工作&#xff1a; 1、申请免费域名&#xff08;也可以花钱注册域名相对稳定&#xff09;链接: 申请免费域名方法 2、申请免费主机&#xff08;也可以…

第8次实验:UDP

目的&#xff1a; 来看一下UDP&#xff08;用户数据报协议&#xff09;的细节。UDP是整个互联网上使用的一种传输协议。在不需要可靠性的情况下&#xff0c;作为TCP的替代品在互联网上使用。它在你的课文的第6.4节中有所涉及。在做这个实验之前&#xff0c;先复习一下这一部分 …