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

httpslocalhostindex 配置的nginx,一刷新就报404了
当你的Nginx配置导致页面刷新时报404错误时,通常是由于以下几个原因造成的: 静态文件路径配置错误:Nginx没有正确地指向静态文件的目录。前端路由问题:如果是SPA(单页应用),刷新页面时Nginx没有…...

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

IO Virtualization with Virtio.part 1 [十二]
久等了各位! 本篇开始讲解 IO 虚拟化中的 virtio,我会以 Linux 的 IIC 驱动为例,从 IIC 驱动的非虚拟化实现,到 IIC 驱动的半虚拟化实现,再到最后 X-Hyper 中如何通过 virtio 来实现前后端联系,一步步把 v…...

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

OpenStack系列第四篇:云平台基础功能与操作(Dashboard)
文章目录 1. 镜像(Image)添加镜像查看镜像删除镜像 2. 卷(Volume)创建卷查看卷删除卷 3. 网络(虚拟网络)创建网络查看网络删除网络 4. 实例类型创建实例类型查看实例类型删除实例类型 4. 密钥对(…...

ESP32 I2S音频总线学习笔记(一):初识I2S通信与配置基础
文章目录 简介为什么需要I2S?关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频?位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载…...

25上半年软考高级系统分析师易混淆知识点
第1章 系统工程与信息系统基础 易混淆点1:系统工程生命周期与信息系统的生命周期 1、系统工程生命周期阶段 探索性研究→概念阶段→开发阶段→生产阶段→使用阶段→保障阶段→退役阶段 2、信息系统的生命周期 产生阶段→开发阶段(单个系统开发&…...

采集JSON解析错误的修复
两段采集来的JSON格式: 一: {"hwgOnlineId":"554312", "jiwuChatId":"", "phoneCategoryId":"20006", "cuxiaoSeq":{voucherTitle:1,lh 二: {"pic":&q…...

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

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

MySQL有哪些锁?
1.MySQL有哪些锁? 全局锁表级锁 表锁元数据锁意向锁 行级锁 记录锁间隙锁临键锁临时意向锁 我了解的是MySQL的锁可以分为全局锁、表级锁、行级锁。 我比较熟悉的是表级锁和行级锁,如果我们对表结构进行修改时,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: 在桌面,单击击键盘的Window键,点击出现的白色software按钮图标; Step2: 输入lib,即可自动跳出libre Office, 进行安装; Step3: Have fun with Rocky Linux....

【每日学点鸿蒙知识】长时任务、HarmonyAppProvision申请、preferences、Testing工具、应用保活
1、HarmonyOS 如何解决语音聊天、通信app退后台系统采集播放回调就会停止,回前台未恢复? 关于应用切到后台系统采集播放回调停止的问题原因如下:为了降低设备耗电速度、保障用户使用流畅度,系统会对退至后台的应用进行管控&#…...

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

【图像去噪】论文复现:大道至简!ZS-N2N的Pytorch源码复现,跑通源码,获得指标计算结果,补充保存去噪结果图像代码,代码实现与论文理论对应!
请先看【专栏介绍文章】:【图像去噪(Image Denoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中) 完整代码和训练好的模型权重文件下载链接见本文底…...

2024年中国新能源汽车用车发展怎么样 PaperGPT(一)
概述 在国家政策的强力扶持下,2024年中国新能源汽车市场迎来了新的发展机遇。本文将基于《中国新能源汽车用车报告(2024年)》的数据,对新能源汽车的市场发展和用车趋势概述。 新能源汽车市场发展 政策推动:国家和地…...

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

python 快速排序(Quick Sort)
快速排序(Quick Sort) 快速排序是一种高效的排序算法,采用分治法(Divide and Conquer)策略。它的基本思想是:选择一个基准元素(pivot),将数组分为两部分,使得…...

MySQL数据库——常见慢查询优化方式
本文详细介绍MySQL的慢查询相关概念,分析步骤及其优化方案等。 文章目录 什么是慢查询日志?慢查询日志的相关参数如何启用慢查询日志?方式一:修改配置文件方式二:通过命令动态启用 分析慢查询日志方式一:直…...

【AIGC篇】AIGC 引擎:点燃创作自动化的未来之火
:羑悻的小杀马特.-CSDN博客 未来都是惊喜。你生来本应为高山。并非草芥。 引言: 在当今数字化的时代,人工智能生成内容(AIGC)正以一种前所未有的力量改变着我们的创作领域。它就像一个神秘而强大的魔法师,…...

C语言性能优化:从基础到高级的全面指南
引言 C 语言以其高效、灵活和功能强大而著称,被广泛应用于系统编程、嵌入式开发、游戏开发等领域。然而,要写出高性能的 C 语言代码,需要对 C 语言的特性和底层硬件有深入的了解。本文将详细介绍 C 语言性能优化的背后技术,并通过…...

常用的公共 NTP(网络时间协议)服务器
公共 NTP 服务列表 以下是一些常用的公共 NTP(网络时间协议)服务器,供您参考: 中国地区公共 NTP 服务器 国家授时中心 NTP 服务器:ntp.ntsc.ac.cn中国 NTP 快速授时服务:cn.ntp.org.cn阿里云公共 NTP 服务…...

Kafka中的Topic和Partition有什么关系?
大家好,我是锋哥。今天分享关于【Kafka中的Topic和Partition有什么关系?】面试题。希望对大家有帮助; Kafka中的Topic和Partition有什么关系? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Apache Kafka 中&#…...

Unity 使用UGUI制作卷轴开启关闭效果
视频效果 代码 using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options;public class JuanZhou : MonoBehaviour {[SerializeField]private …...

MarkDown怎么转pdf;Mark Text怎么使用;
MarkDown怎么转pdf 目录 MarkDown怎么转pdf先用CSDN进行编辑,能双向看版式;标题最后直接导出pdfMark Text怎么使用一、界面介绍二、基本操作三、视图模式四、其他功能先用CSDN进行编辑,能双向看版式; 标题最后直接导出pdf Mark Text怎么使用 Mark Text是一款简洁的开源Mar…...

整合版canal ha搭建--基于1.1.4版本
开启MySql Binlog(1)修改MySql配置文件(2)重启MySql服务,查看配置是否生效(3)配置起效果后,创建canal用户,并赋予权限安装canal-admin(1)解压 canal.admin-1…...

QGIS移动图元功能
有时需要在QGIS里面移动一些矢量图层,比如图层的地理配准,网上搜了一些资料没有查看,后来仔细找了下,在编辑-编辑几何图形-移动要素里面,可以移动图层。 注意:移动前先要选择上要移动的图层,之…...