当前位置: 首页 > news >正文

mongoTemplate的复杂组装条件查询

mongoTemplate不像SQL那么灵活,组装条件较为复杂。
如下演示了查询类似于
AND name = ‘张三’ OR age = 12 NOT birthday > 2024-12-31
这类结构的代码示例。

脑子里的范围图:

所有的AND锁定一个范围,再跟所有的OR组成的范围取并集,再剔除所有NOT的范围。

所以

如果没有AND,则表示全范围,那么OR也失去了意义,这时候只看NOT

想象一个场景帮助理解

我是一个女的,找对象的标准是必须是身高一米八以上的(AND),如果他身价一亿以上,那么不到一米八也可以(OR),不过再怎么样,脾气差的我不要(NOT

以下是具体代码:

1.前端传参封装Req:

@Data
class CaseLibrarySearchReq {private Integer page;private Integer size;// 条件组合列表private List<SearchFilterItem> searchFilterItems;
}@Data
class SearchFilterItem {// 过滤项名字private String filterName;// 过滤项值private Object filterValue;// 逻辑连接词private String logicWord;
}

2.mongoTemplate的复杂组装条件查询:

/*** mongodb mongoTemplate的复杂组装条件查询*/
public Map<String, Object> search(CaseLibrarySearchReq caseLibrarySearchReq) {Map<String, Object> data = new HashMap<>();Integer page = caseLibrarySearchReq.getPage();Integer size = caseLibrarySearchReq.getSize();data.put("page", page);data.put("size", size);List<SearchFilterItem> searchFilterItems = caseLibrarySearchReq.getSearchFilterItems();// 必须要满足的条件List<Criteria> andCriteriaList = ListUtil.toList();// 可选的条件List<Criteria> orCriteriaList = ListUtil.toList();// 要排除的条件List<Criteria> notCriteriaList = ListUtil.toList();// 过滤出有效的搜索项,再根据逻辑关键词分组Map<String, List<SearchFilterItem>> validFilterItemsMap = searchFilterItems.stream().filter(item -> item.getFilterValue() != null && StrUtil.isNotBlank(item.getFilterValue().toString())).collect(Collectors.groupingBy(SearchFilterItem::getLogicWord));// 组装过滤项for (Map.Entry<String, List<SearchFilterItem>> entry : validFilterItemsMap.entrySet()) {String logicWord = entry.getKey();List<SearchFilterItem> validFilterItems = entry.getValue();for (SearchFilterItem item : validFilterItems) {String filterName = item.getFilterName();String filterValueStr = item.getFilterValue().toString();// 针对每种字段单独写处理逻辑switch (filterName) {case "case_number":// 精确匹配的字符串处理Criteria caseNumberCriteria = Criteria.where("case_number").is(filterValueStr);if ("AND".equals(logicWord)) {andCriteriaList.add(caseNumberCriteria);} else if ("OR".equals(logicWord)) {orCriteriaList.add(caseNumberCriteria);} else if ("NOT".equals(logicWord)) {notCriteriaList.add(caseNumberCriteria);}break;case "case_name":// 模糊匹配的字符串处理Pattern pattern1 = Pattern.compile("^.*" + filterValueStr + ".*$", Pattern.CASE_INSENSITIVE);Criteria caseNameCriteria = Criteria.where("case_name").regex(pattern1);if ("AND".equals(logicWord)) {andCriteriaList.add(caseNameCriteria);} else if ("OR".equals(logicWord)) {orCriteriaList.add(caseNameCriteria);} else if ("NOT".equals(logicWord)) {notCriteriaList.add(caseNameCriteria);}break;case "public_date":// 日期类型处理String[] split = filterValueStr.split(",");String startDate = split[0];String endDate = split[1];Criteria publicDateCriteria = new Criteria().and("public_date").gte(startDate).lte(endDate);if ("AND".equals(logicWord)) {andCriteriaList.add(publicDateCriteria);} else if ("OR".equals(logicWord)) {orCriteriaList.add(publicDateCriteria);} else if ("NOT".equals(logicWord)) {notCriteriaList.add(publicDateCriteria);}break;default:break;}}}// 至此,过滤项分类组装完毕Criteria finalCriteria = new Criteria();Criteria andOrcriteria;// 如果AND为空,则只看NOTif (CollUtil.isEmpty(andCriteriaList)) {if (CollUtil.isNotEmpty(notCriteriaList)) {finalCriteria = new Criteria().norOperator(notCriteriaList);// 上一行可能会报错,也许跟版本有关,参考下一行调试一下。下面的报错也是一样// finalCriteria = new Criteria().norOperator(notCriteriaList.toArray(new Criteria[notCriteriaList.size()]));}} else {// 组装and 和orList<Criteria> andOrCriteriaList = ListUtil.toList();andOrCriteriaList.add(new Criteria().andOperator(andCriteriaList));if (CollUtil.isNotEmpty(orCriteriaList)) {andOrCriteriaList.add(new Criteria().orOperator(orCriteriaList));}// 把and 和not合并andOrcriteria = new Criteria().orOperator(andOrCriteriaList);// 如果 notCriteriaList 不为空if (CollUtil.isNotEmpty(notCriteriaList)) {finalCriteria = new Criteria().andOperator(andOrcriteria,new Criteria().norOperator(notCriteriaList));} else {finalCriteria = andOrcriteria;}}Query queryCount = new Query();queryCount.addCriteria(finalCriteria);// 异步任务1 (查询数量,因为mongoTemplate的分页无法返回总数)CompletableFuture<Void> task1 = this.queryTotalCount(data, queryCount);// 分页参数     注意分页时,页码数是从0开始,所以要-1PageRequest pageRequest = PageRequest.of(page - 1, size);Query queryList = new Query();queryList.addCriteria(finalCriteria);queryList.with(pageRequest);// 排序字段Sort sort = Sort.by(Sort.Direction.DESC, "public_date");queryList.with(sort);// 异步任务2    (查询分页列表)CompletableFuture<Void> task2 = this.querySearchList(data, queryList);// 等待所有任务执行完成CompletableFuture.allOf(task1, task2).join();return data;
}

3.计算count:

/*** 计算count*/
public CompletableFuture<Void> caseLibraryCount(Map<String, Object> data, Query query) {return CompletableFuture.runAsync(() -> {try {long total = mongoTemplate.count(query, CaseLibrarySearchVO.class, "case_library");data.put("total", total);} catch (Exception e) {log.error("计算count失败", e);}});
}

4.查询列表:

/*** 查询列表*/
public CompletableFuture<Void> caseLibrarySearchList(Map<String, Object> data, Query query) {return CompletableFuture.runAsync(() -> {try {// 执行分页查询List<CaseLibrarySearchVO> caseLibraryEntityList = mongoTemplate.find(query, CaseLibrarySearchVO.class, "case_library");data.put("caseLibraryEntityList", caseLibraryEntityList);} catch (Exception e) {log.error("查询列表失败", e);}});
}

相关文章:

mongoTemplate的复杂组装条件查询

mongoTemplate不像SQL那么灵活&#xff0c;组装条件较为复杂。 如下演示了查询类似于 AND name ‘张三’ OR age 12 NOT birthday > 2024-12-31 这类结构的代码示例。 脑子里的范围图&#xff1a; 所有的AND锁定一个范围&#xff0c;再跟所有的OR组成的范围取并集&#…...

httpslocalhostindex 配置的nginx,一刷新就报404了

当你的Nginx配置导致页面刷新时报404错误时&#xff0c;通常是由于以下几个原因造成的&#xff1a; 静态文件路径配置错误&#xff1a;Nginx没有正确地指向静态文件的目录。前端路由问题&#xff1a;如果是SPA&#xff08;单页应用&#xff09;&#xff0c;刷新页面时Nginx没有…...

pandas删除值全部为0的整行和整列,还有0.0,0.000000也要删除

在 Pandas 中&#xff0c;如果需要删除全部为 0 的行或列&#xff0c;可以通过 .all() 方法来判断行或列是否所有元素都为 0&#xff0c;然后删除这些行或列。 代码示例 示例数据&#xff1a; import pandas as pd# 示例数据 data {A: [0, 2, 0, 4],B: [0, 0, 0, 0],C: [0, …...

IO Virtualization with Virtio.part 1 [十二]

久等了各位&#xff01; 本篇开始讲解 IO 虚拟化中的 virtio&#xff0c;我会以 Linux 的 IIC 驱动为例&#xff0c;从 IIC 驱动的非虚拟化实现&#xff0c;到 IIC 驱动的半虚拟化实现&#xff0c;再到最后 X-Hyper 中如何通过 virtio 来实现前后端联系&#xff0c;一步步把 v…...

ShardingSphere-Proxy分表场景:go测试案例

接续上篇文章《ShardingSphere-Proxy分表场景测试案例》 go测试用例&#xff1a; package mainimport ("fmt""math/rand""time""github.com/bwmarrin/snowflake""gorm.io/driver/mysql""gorm.io/gorm""gor…...

OpenStack系列第四篇:云平台基础功能与操作(Dashboard)

文章目录 1. 镜像&#xff08;Image&#xff09;添加镜像查看镜像删除镜像 2. 卷&#xff08;Volume&#xff09;创建卷查看卷删除卷 3. 网络&#xff08;虚拟网络&#xff09;创建网络查看网络删除网络 4. 实例类型创建实例类型查看实例类型删除实例类型 4. 密钥对&#xff08…...

ESP32 I2S音频总线学习笔记(一):初识I2S通信与配置基础

文章目录 简介为什么需要I2S&#xff1f;关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频&#xff1f;位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载…...

25上半年软考高级系统分析师易混淆知识点

第1章 系统工程与信息系统基础 易混淆点1&#xff1a;系统工程生命周期与信息系统的生命周期 1、系统工程生命周期阶段 探索性研究→概念阶段→开发阶段→生产阶段→使用阶段→保障阶段→退役阶段 2、信息系统的生命周期 产生阶段→开发阶段&#xff08;单个系统开发&…...

采集JSON解析错误的修复

两段采集来的JSON格式&#xff1a; 一&#xff1a; {"hwgOnlineId":"554312", "jiwuChatId":"", "phoneCategoryId":"20006", "cuxiaoSeq":{voucherTitle:1,lh 二&#xff1a; {"pic":&q…...

Java中实现对象的深拷贝(Deep Copy)

在Java中实现对象的深拷贝&#xff08;Deep Copy&#xff09;意味着创建一个对象的副本&#xff0c;使得原对象和副本对象完全分离&#xff0c;对副本对象的任何修改都不会影响到原对象。以下是几种实现深拷贝的方法&#xff1a; 1. 手动实现深拷贝 对于自定义类&#xff0c;…...

位置编码-APE

Transformer 中的绝对位置编码 &#xff08;以下由gpt 生成&#xff09; Transformer 的绝对位置编码&#xff08;Absolute Position Encoding, APE&#xff09;是用于对序列数据中的位置信息进行建模的一种方法。在 Transformer 的架构中&#xff0c;输入数据&#xff08;如句…...

MySQL有哪些锁?

1.MySQL有哪些锁&#xff1f; 全局锁表级锁 表锁元数据锁意向锁 行级锁 记录锁间隙锁临键锁临时意向锁 我了解的是MySQL的锁可以分为全局锁、表级锁、行级锁。 我比较熟悉的是表级锁和行级锁&#xff0c;如果我们对表结构进行修改时&#xff0c;MySQL就会对这个表结构加一个…...

Everything实现,快速搜索文件

最近编写NTFS文件实时搜索工具, 类似 Everything 这样, 翻阅了很多博客, 结果大致如下: 1.分析比较肤浅, 采用USN日志枚举来获取文件记录 速度一言难尽, 因为日志枚举的是全盘所有文件的所有日志, 记录比文件记录还多, 速度当然很慢, 还有的甚至于是 使用 DeviceIoControl 函数…...

[硬件] DELL BIOS 相关注意事项

前言 前段时间重装系统. DELL BIOS属实资料少, 又难用. 这里给出相关的注意事项, 并且配上图片. BIOS相关注意事项 进入BIOS ESC/F2/ F12. 都可以进入BIOS, 当进U盘的入Win PE系统时, 使用F12 效果更佳. 关闭安全模式 切换到Boot Configuration选项,将Secure Boot选项off选…...

Rocky Linux 下安装Liboffice

Rocky Linux下安装Liboffice。 Step1: 在桌面&#xff0c;单击击键盘的Window键&#xff0c;点击出现的白色software按钮图标&#xff1b; Step2: 输入lib&#xff0c;即可自动跳出libre Office, 进行安装&#xff1b; Step3: Have fun with Rocky Linux....

【每日学点鸿蒙知识】长时任务、HarmonyAppProvision申请、preferences、Testing工具、应用保活

1、HarmonyOS 如何解决语音聊天、通信app退后台系统采集播放回调就会停止&#xff0c;回前台未恢复&#xff1f; 关于应用切到后台系统采集播放回调停止的问题原因如下&#xff1a;为了降低设备耗电速度、保障用户使用流畅度&#xff0c;系统会对退至后台的应用进行管控&#…...

步进电机驱动算法——S形加减速算法原理

1. 前言&#xff1a; 最近项目又用到了步进电机&#xff0c;为了在运动中加减速更加平稳决定研究一下S型加减速&#xff0c;原来用过野火的s型加减速程序&#xff0c;云里雾里的移植成功了&#xff0c;今天再翻来程序看一脸懵逼&#xff0c;重新学习了一下发现所有公式都能看懂…...

【图像去噪】论文复现:大道至简!ZS-N2N的Pytorch源码复现,跑通源码,获得指标计算结果,补充保存去噪结果图像代码,代码实现与论文理论对应!

请先看【专栏介绍文章】:【图像去噪(Image Denoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中) 完整代码和训练好的模型权重文件下载链接见本文底…...

2024年中国新能源汽车用车发展怎么样 PaperGPT(一)

概述 在国家政策的强力扶持下&#xff0c;2024年中国新能源汽车市场迎来了新的发展机遇。本文将基于《中国新能源汽车用车报告&#xff08;2024年&#xff09;》的数据&#xff0c;对新能源汽车的市场发展和用车趋势概述。 新能源汽车市场发展 政策推动&#xff1a;国家和地…...

数据结构-排序思想

直接插入排序 将后面的无序区中的元素挨个向前面的有序区中插入。 1.将顺序表中R[0]用作哨兵&#xff0c;按索引i2...n的次序&#xff0c;将R[i]向有序区R[1...i-1]中执行插入操作。 2.插入操作可采取在有序区中从后向前的查找比较和移动的方法。 3.此操作中比较的次数与原序列…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...