spring-data-elasticsearch 3.2.4 实现桶bucket排序去重,实现指定字段的聚合搜索
一、背景
es索引有一个文档CourseIndex,下面是示意:
| creatorId | grade | subject | name | no |
|---|---|---|---|---|
| 1002 | 2 | 70 | 英语听力课程一 | N00232DS9 |
| 1004 | 3 | 80 | 数学口算课程 | N00209DK7 |
| 1003 | 4 | 80 | 物理竞赛课程 | N00642XS2 |
| 1002 | 2 | 80 | 英语听力课程二 | N00432WS3 |
| 1002 | 2 | 90 | 英语听力课程三 | N002312DP5 |
在搜索的时候,搜索条件包括creatorId列表,grade列表,subject列表等,且它们不是固定的字典,而是从文档CourseIndex的已有数据中获取。
假使上面的数据,搜索条件分别是:
creatorId列表
- 1002
- 1003
- 1004
grade列表
- 2
- 3
- 4
subject列表
- 70
- 80
- 90
总结一下需求,对es文档的数据进行桶bucket排序,以达到去重效果。
下面将介绍如何使用spring-data-elasticsearch 3.2.4实现对指定字段的聚合搜索。
pom.xml引入jar包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-elasticsearch</artifactId><version>3.2.4.RELEASE</version></dependency>
二、CourseIndexAggrService.java
import lombok.RequiredArgsConstructor;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;/*** @author xxx*/
@Component
@RequiredArgsConstructor
public class CourseIndexAggrService {private final ElasticsearchRestTemplate elasticsearchRestTemplate;private final CommonConfig commonConfig;private static final String UNIQUE_FIELD = "unique_field";// 需要进行桶排序的字段public static final String CREATOR_ID = "creatorId";public static final String GRADE = "grade";public static final String SUBJECT = "subject";public List<String> findUniqueField(String uniqueField) {NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//TODO 这里boolQueryBuilder是一个空的查询条件// 过滤掉已逻辑删除的记录 // boolQueryBuilder.filter(QueryBuilders.termQuery("deleted", 0));queryBuilder.withQuery(boolQueryBuilder);TermsAggregationBuilder termsAgg = AggregationBuilders.terms(UNIQUE_FIELD).field(uniqueField);queryBuilder.addAggregation(termsAgg);// idx_courseIndex是索引名queryBuilder.withIndices("idx_courseIndex");// CourseIndex是es文档类,见下文AggregatedPage<CourseIndex> resultPage = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), CourseIndex.class);Aggregation aggregation = resultPage.getAggregation(UNIQUE_FIELD);ParsedLongTerms terms = (ParsedLongTerms) aggregation;// 获取桶final List<? extends Terms.Bucket> buckets = terms.getBuckets();// 提取唯一值List<String> uniqueUserIds = new ArrayList<>();for (Terms.Bucket bucket : buckets) {uniqueUserIds.add(bucket.getKeyAsString());}return uniqueUserIds;}
}
三、CourseIndex.java
这里略去了无关本文的字段。
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import javax.persistence.Id;
import java.io.Serializable;
import java.util.Set;/*** 课程索引.* <p>* 索引检索条件,并非所有的字段* </p>** @author xxx*/
@Data
@Document(indexName = "#{commonConfig.courseIdx}", type = "_doc", shards = 1, refreshInterval = "-1")
public class CourseIndex implements Serializable {@Idprivate String id;/*** 课程或讲次编号*/@Field(type = FieldType.Keyword)private String no;/*** 创建者ID*/@Field(type = FieldType.Long)private long creatorId;/*** 课程或讲次名称*/@Field(type = FieldType.Text)private String name;/*** 科目*/@Field(type = FieldType.Integer)private int subject;/*** 年级*/@Field(type = FieldType.Integer)private int grade;
}
四、使用
// 查询创建者creatorId列表
final List<Long> userIds = courseIndexAggrService.findUniqueField(CREATOR_ID).stream().map(v -> Long.parseLong(v)).collect(Collectors.toList());// 查询年级grade列表
final List<Integer> grades = courseIndexAggrService.findUniqueField(GRADE).stream().map(v -> Integer.parseInt(v)).collect(Collectors.toList());// 查询科目subject列表
final List<Integer> subjects = courseIndexAggrService.findUniqueField(SUBJECT).stream().map(v -> Integer.parseInt(v)).collect(Collectors.toList());

相关文章:
spring-data-elasticsearch 3.2.4 实现桶bucket排序去重,实现指定字段的聚合搜索
一、背景 es索引有一个文档CourseIndex,下面是示意: creatorIdgradesubjectnameno1002270英语听力课程一N00232DS91004380数学口算课程N00209DK71003480物理竞赛课程N00642XS21002280英语听力课程二N00432WS31002290英语听力课程三N002312DP5 在搜索的时候&#…...
【项目开发】分析六种常用软件架构
未经许可,不得转载。 文章目录 软件架构核心内容设计原则分层架构常见层次划分优缺点应用场景事件驱动架构核心组件优缺点应用场景微核架构核心概念优缺点应用场景微服务架构核心组件设计与实施优缺点应用场景云架构云架构模式优缺点应用场景软件架构 软件架构是指一个软件系…...
算法和程序的区别
算法(Algorithm)和程序(Program)是计算机科学中两个密切相关但不同的概念。让我们通过以下几个方面来比较它们: ### 1. 设计 vs 实现 - **算法设计(Algorithm Design)**: - **定…...
用指针遍历数组
#include<stdio.h> int main() {//定义一个二维数组int arr[3][4] {{1,2,3,4},{2,3,4,5},{3,4,5,6},};//获取二维数组的指针int (*p)[4] arr;//二维数组里存的是一维数组int[4]for (int i 0; i < 3; i){//遍历一维数组for (int j 0; j <4; j){printf("%d &…...
《Probing the 3D Awareness of Visual Foundation Models》论文解析——多视图一致性
一、论文简介 论文讨论了大规模预训练产生的视觉基础模型在处理任意图像时的强大能力,这些模型不仅能够完成训练任务,其中间表示还对其他视觉任务(如检测和分割)有用。研究者们提出了一个问题:这些模型是否能够表示物体…...
使用pip安装esp32的擦除、写入固件的esptool库
esptool库可以为esp32的开发板烧录新的固件,但是如果为了烧录固件就要装esp-idf软件包,甚至需要用make编译安装很久,实在太费时费力了! 好消息就是,esp提供了python的esptool库,这样只要使用pip安装上这个…...
传奇996_23——杀怪掉落,自动捡取,捡取动画
一、杀怪掉落 前置: 添加地图地图刷怪怪物掉落(术语叫爆率,掉落叫爆率,而且文档上叫爆率) 刷怪步骤:在\MirServer\Mir200\Envir\MonItems文件夹中建立以怪物名字为文件名的txt文件写法案例: …...
【030】基于51单片机甲醛检测报警器【Proteus仿真+Keil程序+报告+原理图】
☆、设计硬件组成:51单片机最小系统 ZE08-CH2O甲醛传感器AT24C02存储芯片LCD1602液晶显示按键设置蜂鸣器报警。 1、本设计采用STC89C52、AT89C52、AT89S52作为主控芯片; 2、采用ZE08-CH2O甲醛传感器采集环境中的甲醛浓度值,LCD1602实时显示…...
微信小程序:vant组件库安装步骤
前言:在微信小程序中引用vant组件报错,提示路径不存在,这很有可能是因为没有安装构建vant组件库导致。下面是我整理的安装vant组件库的步骤: 第一步:安装node.js(执行完第一步请重启小程序) 具体步骤请看链接:node.js…...
处理namespace问题:Namespace not specified for AGP 8.0.0
How do I fix ‘namespace not specified’ error in Android Studio? Namespace not specified for AGP 8.0.0 解决方案 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/androi…...
C++(Qt)软件调试---内存分析工具Heob(26)
C(Qt)软件调试—内存分析工具Heob(26) 文章目录 C(Qt)软件调试---内存分析工具Heob(26)[toc]1、概述🐜2、环境配置🪲3、功能说明4、使用Heob分析qt 程序内存泄漏🦧5、使用Heob检测qt 程序野指针…...
Redis五大基本类型——String字符串命令详解(命令用法详解+思维导图详解)
目录 一、String字符串类型介绍 二、常见命令 1、SET 2、GET 3、MGET 4、MSET 使用MGET 和 使用多次GET的区别 5、DEL 6、SETNX SET、SET NX和SET XX执行流程 7、INCR 8、INCRBY 9、DECR 10、DECYBY 11、INCRBYFLOAT 12、APPEND 13、GETRANGE 14、SETRANGE …...
Flutter中的Material Theme完全指南:从入门到实战
Flutter作为一款热门的跨平台开发框架,其UI组件库Material Design深受开发者喜爱。本文将深入探讨Flutter Material Theme的使用,包括如何借助Material Theme Builder创建符合产品需求的主题风格。通过多个场景和代码实例,让你轻松掌握这一工…...
Python 第三方库 PyQt5 的安装
目录 前言 PyQt5安装 不同操作系统PyQt5安装 一、Windows 系统 二、macOS 系统 三、Linux 系统(以 Ubuntu 为例) 安装 PyQt5 可能会遇到的问题 一、环境相关问题 二、依赖问题 三、网络问题 四、安装工具问题 五、运行时问题 六、环境配置问…...
CSS基础也要进行模电实验
盒子阴影 圆角边框已经介绍过哩,现在先介绍一下盒子阴影的效果如何实现 CSS3中新增了盒子阴影,可以使用box-shadow属性为盒子添加阴影 这是固定的语法: text-shadow: h-shadow v-shadow blur color; 它有这些可选的值: 哦。 …...
贴代码框架PasteForm特性介绍之markdown和richtext
简介 PasteForm是贴代码推出的 “新一代CRUD” ,基于ABPvNext,目的是通过对Dto的特性的标注,从而实现管理端的统一UI,借助于配套的PasteBuilder代码生成器,你可以快速的为自己的项目构建后台管理端!目前管…...
3D Gaussian Splatting 代码层理解之Part3
最后,内容到达了高斯泼溅过程中最有趣的阶段:渲染!这一步可以说是最关键的,因为它决定了模型的真实性。然而,它也可能是最简单的。在本系列的Part 1和Part2,文章演示了如何将 Raw 3D椭球 转换为可渲染的格式,但现在我们实际上必须完成这项工作并渲染到一组固定的像素上。…...
Ceph 中PG与PGP的概述
在Ceph分布式存储系统中,PG(Placement Group)和PGP(Placement Group for Placement purpose)是两个至关重要的概念,它们共同决定了数据在集群中的分布和复制方式。以下是关于Ceph中PG和PGP关系的详细解释&a…...
已解决:spark代码中sqlContext.createDataframe空指针异常
这段代码是使用local模式运行spark代码。但是在获取了spark.sqlContext之后,用sqlContext将rdd算子转换为Dataframe的时候报错空指针异常 Exception in thread "main" org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.lang.Nu…...
flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例
flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例 Android iOS设备带有选择记录 我的flutter项目版本 environment: sdk: ‘>3.4.4 <4.0.0’ 图片案例 pubspec.yaml 添加依赖 # 屏幕尺寸适配 https://github.com/OpenF…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
