如何使用Spring Data MongoDB Criteria实现子列表被指定列表包含的查询
MongoDB列表包含查询实现
需求场景
需要查询文档中指定列表字段的所有元素都被包含在给定列表内的记录,示例数据如下:
{_id:1,list:[1,2,3,4]} {_id:2,list:[1]} {_id:3,list:[1,3,4,6]}
如果给定查询列表为 L = [1,2,3,4,5],则符合要求的是_id为1、2的文档,_id为3的文档因包含不在L中的元素6会被排除。
原生MongoDB查询逻辑
方案1:使用$setIsSubset集合运算(推荐,性能更高)
通过MongoDB内置的集合子集判断运算符实现,查询语句如下:
db.collection.find({ $expr: { $setIsSubset: ["$list", [1,2,3,4,5]] } })
方案2:使用$not+$elemMatch+$nin(兼容性更好)
反向排除存在元素不在给定列表内的文档,查询语句如下:
db.collection.find({ list: { $not: { $elemMatch: { $nin: [1,2,3,4,5] } } } })
Spring Data MongoDB 正确实现代码
对应方案1的实现(适用于Spring Data MongoDB 2.2及以上版本)
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.bson.Document; import java.util.Arrays; import java.util.List; // 你的实体类 // import com.example.entity.YourEntity; public List<YourEntity> queryMatchedDocs() { // 给定的查询列表 List<Integer> targetList = Arrays.asList(1,2,3,4,5); // 构造查询条件 Criteria criteria = Criteria.where("$expr") .is(new Document("$setIsSubset", Arrays.asList("$list", targetList))); Query query = new Query(criteria); // 执行查询 return mongoTemplate.find(query, YourEntity.class); }
对应方案2的实现(全版本兼容)
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import java.util.Arrays; import java.util.List; // 你的实体类 // import com.example.entity.YourEntity; public List<YourEntity> queryMatchedDocs() { // 给定的查询列表 List<Integer> targetList = Arrays.asList(1,2,3,4,5); // 构造查询条件:排除list字段存在元素不在targetList中的文档 Criteria criteria = Criteria.where("list").not() .elemMatch(Criteria.where("$nin").is(targetList)); Query query = new Query(criteria); // 执行查询 return mongoTemplate.find(query, YourEntity.class); }
常见错误说明
如果查询返回所有文档,大概率是误用了$all运算符:$all是要求给定列表的所有元素都出现在文档的列表字段中,和当前需求逻辑完全相反,注意不要混淆。
内容的提问来源于stack exchange,提问作者Shameera Anuranga
相关产品推荐
相关产品推荐

