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

MongoTemplate 中如何构建复杂的查询条件 (Criteria API)?

Spring Data MongoDB 提供了强大的 Criteria API,允许我们以编程方式构建复杂的 MongoDB 查询条件。

核心类是 org.springframework.data.mongodb.core.query.Criteriaorg.springframework.data.mongodb.core.query.Query

基本步骤:

  1. 创建一个 Query 对象。
  2. 使用 Criteria.where("fieldName") 开始定义条件。
  3. 链接各种条件方法 (is(), gt(), lt(), regex(), in(), andOperator(), orOperator() 等)。
  4. 将构建好的 Criteria 添加到 Query 对象中 (query.addCriteria(criteria))。
  5. 使用 MongoTemplate 执行查询。

常用操作符和方法:

1. 比较操作符:

  • is(Object value): 等于 (field: value)
  • ne(Object value): 不等于 (field: { $ne: value })
  • lt(Object value): 小于 (field: { $lt: value })
  • lte(Object value): 小于等于 (field: { $lte: value })
  • gt(Object value): 大于 (field: { $gt: value })
  • gte(Object value): 大于等于 (field: { $gte: value })
  • in(Object... values)in(Collection<?> values): 包含在数组中 (field: { $in: [value1, value2, ...] })
  • nin(Object... values)nin(Collection<?> values): 不包含在数组中 (field: { $nin: [value1, value2, ...] })

示例:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import static org.springframework.data.mongodb.core.query.Criteria.where; // 静态导入更简洁// 假设有一个 User 类和 MongoTemplate 实例
// MongoTemplate mongoTemplate = ...;// 查询年龄为 30 的用户
Query queryAge30 = new Query(where("age").is(30));
List<User> usersAge30 = mongoTemplate.find(queryAge30, User.class);// 查询年龄大于 25 且小于 50 的用户
Query queryAgeRange = new Query(where("age").gt(25).lt(50));
// 等价于: Query queryAgeRange = new Query(new Criteria().andOperator(where("age").gt(25), where("age").lt(50)));
List<User> usersInRange = mongoTemplate.find(queryAgeRange, User.class);// 查询名字是 "Alice" 或 "Bob" 的用户
Query queryNames = new Query(where("name").in("Alice", "Bob"));
List<User> usersByNames = mongoTemplate.find(queryNames, User.class);

2. 逻辑操作符:

  • andOperator(Criteria... criteria): AND 条件 ($and: [{crit1}, {crit2}, ...])
  • orOperator(Criteria... criteria): OR 条件 ($or: [{crit1}, {crit2}, ...])
  • norOperator(Criteria... criteria): NOR 条件 ($nor: [{crit1}, {crit2}, ...])
  • not(): NOT 操作 (通常与其他操作符结合, 如 where("age").not().gt(18))

示例:

// 查询 (状态为 "ACTIVE" AND 积分大于 100) OR (是 VIP 用户)
Criteria activeAndPoints = new Criteria().andOperator(where("status").is("ACTIVE"),where("points").gt(100)
);
Criteria isVip = where("isVip").is(true);Query complexQuery = new Query(new Criteria().orOperator(activeAndPoints, isVip));
List<User> complexUsers = mongoTemplate.find(complexQuery, User.class);// 查询不是管理员的用户
Query notAdminQuery = new Query(where("roles").not().is("ADMIN")); // 如果 roles 是单个值
// 如果 roles 是数组,且不想包含 ADMIN:
// Query notAdminQuery = new Query(where("roles").nin("ADMIN"));
// 或者更精确地:Query notAdminQuery = new Query(where("roles").not().elemMatch(where("$eq").is("ADMIN")));

注意关于 and 的 chaining:
当你在同一个 Criteria.where("field") 实例上链式调用多个条件时,它们默认是以 AND 关系应用于 该字段
例如:where("age").gt(20).lt(30) 相当于 { "age": { "$gt": 20, "$lt": 30 } }

如果你需要对 不同字段 进行 AND 操作,可以链式调用 and("otherField"),或者使用 andOperator
where("age").gt(20).and("name").is("Alice") 相当于 { "age": { "$gt": 20 }, "name": "Alice" }
通常,将多个独立的 Criteria 实例通过 query.addCriteria()(隐式 AND)或显式的 andOperator 组合起来更清晰。

3. 元素操作符:

  • exists(boolean value): 字段是否存在 (field: { $exists: true/false })
  • type(int bsonType)type(BsonType bsonType): 字段类型是否匹配 (field: { $type: BsonType })

示例:

import org.bson.BsonType;// 查询有 "email" 字段的用户
Query queryHasEmail = new Query(where("email").exists(true));// 查询 "age" 字段类型为数字 (INT32, INT64, DOUBLE) 的用户
Query queryAgeIsNumber = new Query(where("age").type(BsonType.INT32)); // 或者 BsonType.DOUBLE, BsonType.INT64
// 或者更通用地查询多种数字类型:
// Query queryAgeIsNumber = new Query(new Criteria().orOperator(
//     where("age").type(BsonType.INT32),
//     where("age").type(BsonType.INT64),
//     where("age").type(BsonType.DOUBLE)
// ));List<User> usersWithEmail = mongoTemplate.find(queryHasEmail, User.class);

4. 数组操作符:

  • all(Object... values)all(Collection<?> values): 数组字段包含所有指定元素 (field: { $all: [value1, value2, ...] })
  • elemMatch(Criteria criteria): 数组字段中至少有一个元素匹配指定的 Criteria (field: { $elemMatch: { criteria } })
  • size(int s): 数组字段的长度等于 s (field: { $size: s })

示例:

// 假设 User 有一个 List<String> tags 字段// 查询标签同时包含 "java" 和 "mongodb" 的用户
Query queryTagsAll = new Query(where("tags").all("java", "mongodb"));// 查询订单列表中至少有一个订单金额大于 100 的用户
// 假设 User 有一个 List<Order> orders 字段,Order 有 amount 字段
Query queryOrderAmount = new Query(where("orders").elemMatch(where("amount").gt(100)));// 查询有 3 个标签的用户
Query queryTagsSize = new Query(where("tags").size(3));

5. 正则表达式操作符:

  • regex(String re): 匹配正则表达式 (field: /re/)
  • regex(String re, String options): 匹配正则表达式并指定选项 (如 “i” 忽略大小写) (field: { $regex: re, $options: 'i' })
  • regex(Pattern pattern): 使用 Java Pattern 对象

示例:

// 查询名字以 "A" 开头的用户 (忽略大小写)
Query queryNameStartsWithA = new Query(where("name").regex("^A", "i"));
// 或者使用 Pattern
// Pattern pattern = Pattern.compile("^A", Pattern.CASE_INSENSITIVE);
// Query queryNameStartsWithA = new Query(where("name").regex(pattern));List<User> usersStartsWithA = mongoTemplate.find(queryNameStartsWithA, User.class);

6. 文本搜索 (Text Search):

需要集合中有文本索引 (@TextIndexed 注解或手动创建)。

  • 使用 TextCriteriaTextQuery

示例:

import org.springframework.data.mongodb.core.query.TextCriteria;
import org.springframework.data.mongodb.core.query.TextQuery;// 假设 description 字段有文本索引
// 搜索描述中包含 "database" 或 "system" 的文档,并按相关性排序
TextCriteria textCriteria = TextCriteria.forDefaultLanguage().matchingAny("database", "system");Query textSearchQuery = TextQuery.queryText(textCriteria).sortByScore(); // 按文本搜索得分排序List<Product> products = mongoTemplate.find(textSearchQuery, Product.class);

7. 地理空间查询 (Geospatial Queries):

需要地理空间索引。

  • within(Shape shape): 在指定形状内 (如 $geoWithin$box, $polygon, $centerSphere)
  • near(Point point): 靠近某个点 ($near)
  • nearSphere(Point point): 在球面上靠近某个点 ($nearSphere)
  • maxDistance(double maxDistance): 与 nearnearSphere 结合使用,限制最大距离

示例:

import org.springframework.data.geo.Point;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Box;// 假设 Venue 有一个 GeoJsonPoint location 字段,并有 2dsphere 索引// 查询坐标点 (longitude, latitude) 附近 10 公里内的地点
Point centerPoint = new Point(-73.9667, 40.78); // 经度, 纬度
Distance maxDistance = new Distance(10, Metrics.KILOMETERS);
Query nearQuery = new Query(where("location").nearSphere(centerPoint).maxDistance(maxDistance.getNormalizedValue()));
// maxDistance.getNormalizedValue() 将距离转换为弧度 (对于 $nearSphere)List<Venue> nearbyVenues = mongoTemplate.find(nearQuery, Venue.class);// 查询在指定矩形区域内的地点
Point lowerLeft = new Point(-74.0, 40.7);
Point upperRight = new Point(-73.9, 40.8);
Box boundingBox = new Box(lowerLeft, upperRight);
Query withinBoxQuery = new Query(where("location").within(boundingBox));List<Venue> venuesInBox = mongoTemplate.find(withinBoxQuery, Venue.class);

8. 嵌套文档查询:

使用点表示法 (.):

// 假设 User 有一个内嵌的 Address 对象,Address 有 city 字段
// Address { String street; String city; String zipCode; }
// User { ..., Address address; ... }// 查询城市为 "New York" 的用户
Query queryCity = new Query(where("address.city").is("New York"));
List<User> usersInNewYork = mongoTemplate.find(queryCity, User.class);

组合多个 Criteria 到 Query 中:

默认情况下,如果你多次调用 query.addCriteria(),它们之间是 AND 关系。

Query query = new Query();
query.addCriteria(where("status").is("ACTIVE")); // 条件1
query.addCriteria(where("age").gt(18));          // 条件2 (与条件1是AND关系)
// 等效于 { "status": "ACTIVE", "age": { "$gt": 18 } }
// 或 query.addCriteria(new Criteria().andOperator(where("status").is("ACTIVE"), where("age").gt(18)));

构建复杂查询的技巧:

  • 静态导入: import static org.springframework.data.mongodb.core.query.Criteria.where; 使代码更简洁。
  • 分步构建: 将复杂的逻辑分解成多个小的 Criteria 对象,然后使用 andOperatororOperator 组合它们。
  • 可读性: 适当使用变量名来描述每个 Criteria 部分的含义。
  • 链式调用: 充分利用链式API。

示例:一个更复杂的组合查询

查询所有 (年龄大于20且城市是"London") 或者 (是VIP客户且最近登录在过去7天内) 的用户。

import java.time.LocalDateTime;Criteria ageAndCity = new Criteria().andOperator(where("age").gt(20),where("address.city").is("London")
);Criteria vipAndRecentLogin = new Criteria().andOperator(where("isVip").is(true),where("lastLoginDate").gte(LocalDateTime.now().minusDays(7))
);Query finalQuery = new Query(new Criteria().orOperator(ageAndCity, vipAndRecentLogin));// 添加排序
// import org.springframework.data.domain.Sort;
// finalQuery.with(Sort.by(Sort.Direction.DESC, "registrationDate"));// 添加分页
// finalQuery.skip(0);
// finalQuery.limit(10);List<User> resultUsers = mongoTemplate.find(finalQuery, User.class);

Criteria API 为构建 MongoDB 查询提供了非常灵活和强大的方式,几乎可以表达 MongoDB 支持的所有查询操作。

相关文章:

  • 智能问数技术路径对比:NL2SQL vs NL2Semantic2SQL
  • 在 Linux 上安装 `pgvector`(这是一个 PostgreSQL 的向量类型扩展,常用于处理嵌入向量,便于进行向量相似度搜索)
  • 四、关系数据库标准语言SQL_1
  • 使用FastAPI+Sqlalchemy从一个数据库向另一个数据库更新数据(sql语句版)
  • 大规模JSON反序列化性能优化实战:Jackson vs FastJSON深度对比与定制化改造
  • MySQL常见故障排查与性能优化
  • React从基础入门到高级实战:React 高级主题 - 性能优化:深入探索与实践指南
  • Bean对象循环依赖
  • 探索C++:STL
  • 【机械视觉】Halcon—【六、交集并集差集和仿射变换】
  • DeepSeek‑R1-0528 重磅升级:蚂蚁百宝箱免费、无限量调用
  • 探索三维螺旋线的几何奥秘:曲率与挠率的计算与可视化
  • 线程池的详细知识(含有工厂模式)
  • Flask与PostgreSQL交互教程
  • Python Day37 学习
  • LangChain整合Milvus向量数据库实战:数据新增与删除操作
  • 【Zephyr 系列 2】用 Zephyr 玩转 Arduino UNO / MEGA,实现串口通信与 CLI 命令交互
  • 一带一路暨金砖国家技能发展与技术创新大赛背景下,”工业互联网+绿色低碳”实训方案
  • [特殊字符] xbatis 一款好用 ORM 框架 1.8.8-M2 发布,节省 1/3 代码和时间的框架!!!
  • 卫星地图 App 的实测体验深度解析
  • 怎样做自己的网站和发布网站/长沙网站优化对策
  • 响应式网站 手机站/免费关键词挖掘工具
  • 住房和城乡建设网站 上海/免费永久注册顶级域名网站
  • 企业平台网站建设/百度售后服务电话
  • 做网站什么什么/十大收益最好的自媒体平台
  • 网站信息资料库建设/百度关键词优化专家