MongoDB单查询实现C1过滤结果关联C2及多条件计数
没问题,这需求用MongoDB的聚合管道就能搞定单条查询实现,我给你拆解下步骤,再附上Java Spring里的代码实现~
原生MongoDB聚合查询语句
先看直接在MongoDB shell里能跑的原生查询,逻辑清晰易懂:
db.C1.aggregate([ // 第一步:筛选C1中special为foo的记录,减少后续处理量 { $match: { "special": "foo" } }, // 第二步:关联C2集合,把匹配的记录存入c2字段 { $lookup: { from: "C2", localField: "related", foreignField: "name", as: "c2" } }, // 第三步:计算三个计数字段 { $addFields: { lowCount: { $size: { $filter: { input: "$c2", cond: { $lte: ["$$this.total", 100] } } } }, midCount: { $size: { $filter: { input: "$c2", cond: { $and: [{ $gt: ["$$this.total", 100] }, { $lte: ["$$this.total", 500] }] } } } }, highCount: { $size: { $filter: { input: "$c2", cond: { $gt: ["$$this.total", 500] } } } } } } ])
各阶段说明
- $match:先把符合条件的C1记录筛选出来,避免后续处理无关数据,提升性能
- $lookup:相当于SQL的左关联,把C2中
name与当前C1记录related匹配的所有结果,打包成数组存入c2字段(兼容一对一/一对多的匹配场景) - $addFields:通过
$filter从c2数组里捞符合计数条件的元素,再用$size获取数组长度,得到对应的统计数
Java Spring框架实现(基于MongoTemplate)
如果用Spring Data MongoDB的MongoTemplate,可以这样写代码,完全对应上面的聚合逻辑:
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.aggregation.LookupOperation; import org.springframework.data.mongodb.core.query.Criteria; import java.util.List; // 假设你的C1实体类是C1Document,记得要包含c2、lowCount、midCount、highCount字段 public List<C1Document> getFilteredDataWithCounts(MongoTemplate mongoTemplate) { // 构建$match阶段 AggregationOperation matchStage = Aggregation.match(Criteria.where("special").is("foo")); // 构建$lookup阶段 LookupOperation lookupStage = LookupOperation.newLookup() .from("C2") .localField("related") .foreignField("name") .as("c2"); // 构建$addFields阶段,计算三个计数字段 AggregationOperation addFieldsStage = Aggregation.addFields() .addFieldWithValue("lowCount", Aggregation.size(Aggregation.filter("c2", "item", Criteria.where("$$item.total").lte(100).getCriteriaObject()))) .addFieldWithValue("midCount", Aggregation.size(Aggregation.filter("c2", "item", Criteria.where("$$item.total").gt(100).lte(500).getCriteriaObject()))) .addFieldWithValue("highCount", Aggregation.size(Aggregation.filter("c2", "item", Criteria.where("$$item.total").gt(500).getCriteriaObject()))) .build(); // 组装并执行聚合查询 Aggregation aggregation = Aggregation.newAggregation(matchStage, lookupStage, addFieldsStage); return mongoTemplate.aggregate(aggregation, "C1", C1Document.class).getMappedResults(); }
注意事项
- 你的
C1Document实体类需要添加对应字段:比如用@Field("c2") private List<C2Document> c2;来映射关联结果,private Integer lowCount;等字段来接收统计值 - 如果C2也有实体类
C2Document,Spring会自动完成数据映射,不用手动处理
内容的提问来源于stack exchange,提问作者Aankhen
相关产品推荐
相关产品推荐

