如何统计MongoDB中文档内boats数组中price为200的对象数量?
解决MongoDB数组元素统计问题
嗨,刚接触MongoDB很容易踩这个坑,我来给你梳理清楚问题和解决办法!
为什么你的查询返回1?
你原来的查询db.getCollection('boatsCompany').find({'price' : 200}).count()其实有两个关键问题:
price字段是嵌套在boats数组的子对象里的,直接查price:200根本匹配不到任何父文档(父级文档本身没有这个字段)——如果实际运行返回1,大概率是你后来改成了find({"boats.price":200});- 哪怕查询条件改对了,
count()统计的是匹配的父文档数量,而不是数组里符合条件的子元素数量。哪怕你的boats数组里有10个price=200的对象,只要这个父文档包含至少一个,就只会被算成1。
正确的统计方法
要统计数组里符合条件的元素总数,我们需要用MongoDB的聚合框架,这里有两种常用方案:
方案1:用$unwind展开数组后统计
这个方法直观易懂,适合新手理解:
db.boatsCompany.aggregate([ // 将boats数组拆分成单个文档,每个数组元素对应一个中间文档 { $unwind: "$boats" }, // 筛选出boats.price等于200的中间文档 { $match: { "boats.price": 200 } }, // 统计符合条件的文档总数(也就是原数组里的元素数量) { $count: "total_matching_boats" } ])
执行后会返回类似{ "total_matching_boats": 3 }的结果,数字就是你要的总数。
方案2:用$filter+$size直接计算(更高效)
如果你的数组很大,$unwind会生成大量中间文档,这时可以用$filter在数组内部筛选符合条件的元素,再用$size获取数量,最后求和:
db.boatsCompany.aggregate([ // 给每个父文档添加一个字段,记录该文档内符合条件的boats数量 { $addFields: { matching_count: { $size: { $filter: { input: "$boats", // 要处理的数组 cond: { $eq: ["$$this.price", 200] } // 筛选条件:当前元素的price等于200 } } } } }, // 把所有父文档的matching_count加起来,得到全局总数 { $group: { _id: null, total: { $sum: "$matching_count" } } } ])
这个方法不需要拆分数组,性能更好,尤其适合大集合场景。
小提示
如果你的集合里只有一个父文档(就像你例子里的那样),两种方法都会得到相同的结果。如果有多个父文档,两种方法都会统计所有文档里的符合条件的boats元素总数。
内容的提问来源于stack exchange,提问作者Rodr
相关产品推荐
相关产品推荐

