应使用 MongoTemplate + Criteria 分步构建动态查询:AND 条件需先 new Criteria 再按需 add;OR 条件用 orOperator() 配合循环构造 Criteria 列表;聚合查询用 List 收集阶段再转数组;务必校验空值避免崩溃。

别用 findByXXXAndYYY 拼方法名,也别硬写 @Query 字符串模板——动态条件一多,前者爆炸式增长,后者根本没法 debug。真正可维护的方案是:用 MongoTemplate + Criteria 构建查询对象,配合条件组装逻辑,把“是否启用某条件”变成布尔判断,而不是字符串拼接。
动态组合 AND 条件时,Criteria 要链式调用还是分步构建?
链式调用(如 where("status").is("active").and("price").gte(100))只适合固定条件;一旦某个字段是否参与查询取决于运行时参数(比如前端传了 minPrice 才加价格范围),就必须分步构建 Criteria 实例。
- 错误做法:不管参数有没有值,都往链式表达式里塞
.and("tags").in(tags),空集合会查出全表或报错 - 正确做法:先 new 一个空
Criteria,再按需.add()子条件 - 注意
Criteria.andOperator()和Criteria.orOperator()的入参必须是非空列表,传空集合会抛IllegalArgumentException
OR 查询怎么避免手写一堆 if-else?
当用户输入多个关键词(如搜索框支持“张三 OR 李四 OR 王五”),直接用 orOperator() 配合循环构造 Criteria 列表最干净。
- 别用字符串拼
$or: [{name:"张三"},{name:"李四"}]—— 这种写法绕过类型检查,字段名写错 runtime 才暴露 - 用
new ArrayList()收集每个Criteria.where("name").is(keyword),最后传给orOperator() - 如果 OR 条件本身带子条件(比如
(name="张三" AND age>20) OR (status="active")),就对每个分支单独 newCriteria,再塞进 or 列表
聚合查询里动态加 $match 阶段,Aggregation 怎么拼?
Aggregation.newAggregation() 接收的是可变参数,不能中途插入。要动态加 $match,得先把所有可能的阶段放进 list,再转成数组传入。
- 错误写法:
Aggregation.newAggregation(match1, match2, group, sort)—— 如果match2可能为空,就得写三套调用 - 正确写法:用
List收集阶段,if (hasDateRange) ops.add(Aggregation.match(dateCriteria)),最后Aggregation.newAggregation(ops.toArray(new AggregationOperation[0])) - 特别注意:$match 尽量前置,否则索引失效;
Aggregation.match()的Criteria必须是真实存在的字段,别传 null 或空字符串进去
最常被忽略的点是空值处理——Criteria 对 null 值不敏感,但对空字符串、空集合、未初始化的 List 会直接崩。每次 add 条件前,先做 Objects.nonNull() 或 CollectionUtils.isNotEmpty() 判断,比事后查日志快十倍。











