MongoDB聚合查询:同时展示col1字段与col2符合条件文档计数
我来帮你搞定这个问题!你的核心需求是同时获取col1里的name、status字段,以及每个col1文档对应的col2中符合条件(ycode匹配col1._id、scode不为null)的文档数量。原查询的问题出在$count阶段——这个阶段会直接丢弃所有原有字段,只返回计数结果,所以才会出现“要么有计数没字段,要么有字段没计数”的矛盾。
正确的聚合查询方案
我们可以利用$lookup返回的匹配数组,直接用$size统计数组长度来得到计数,同时保留原col1的字段:
db.col1.aggregate([ // 第一步:筛选col1中city为city1的文档 {'$match': { city: 'city1' } }, // 第二步:关联col2,筛选符合条件的文档到数组中 { $lookup: { from: "col2", let: { ycode: "$_id", city: "$city" }, pipeline: [ { $match: { scode: { '$ne': null }, lockedDate: ISODate("2020-05-20T00:00:00Z"), $expr: { $and: [ { $eq: [ "$ycode", "$$ycode" ] }, { $eq: [ "$city", "$$city" ] } ] } } } ], as: "matched_col2_docs" } }, // 第三步:添加计数字段,统计匹配的col2文档数量 { $addFields: { matched_count: { $size: "$matched_col2_docs" } } }, // 第四步:只保留需要返回的字段 { $project: { name: 1, status: 1, matched_count: 1, _id: 0 // 可选,不需要_id的话可以加上这行 } } ])
方案说明
- $lookup阶段:会为每个
col1文档返回一个包含所有匹配col2文档的数组matched_col2_docs,这里已经通过pipeline筛选了scode不为null、lockedDate匹配、ycode和city对应的条件。 - $addFields阶段:用
$size函数计算matched_col2_docs数组的长度,得到我们需要的计数,并存入matched_count字段。 - $project阶段:只保留我们需要的
name、status和matched_count字段,去掉不需要的内容。
原查询的问题分析
- 原查询中使用
$unwind会把每个匹配的col2文档展开成单独的文档,之后的$count是统计所有展开后的总数量,而不是每个col1文档对应的匹配数。 $count阶段会直接丢弃所有原有字段,所以无论后面加不加$project,都无法同时保留col1的字段和计数。
这个方案在MongoDB 4.0+和Mongoose 5.x+环境下完全适用,你可以直接测试运行~
内容的提问来源于stack exchange,提问作者sachin.pandey
相关产品推荐
相关产品推荐

