MongoDB/Mongoose聚合统计嵌套文档字段频次时_id值返回异常
问题原因
你遇到的分组结果异常,核心来自聚合流程里冗余的错误$unwind操作:
- 从你提供的测试文档结构可以明确看到,
songStatus是requestList数组下每个子文档的普通字符串标量字段,不存在嵌套数组结构,本身不需要拆解。 - 对非数组的标量字符串字段执行
$unwind时,部分旧版MongoDB会出现嵌套路径解析异常:拆解逻辑没有正确保留原字段值,反而因路径匹配偏差,把所有分组关联的字段值统一识别为测试数据中存在的"queue"字符串,最终出现"计数数值正确、但分组键全错"的反常结果。 - 即使在兼容新版MongoDB上,这个冗余的unwind阶段也会产生不必要的性能开销——新版MongoDB会把非数组的标量值默认当作单元素数组处理,虽然不会出错,但完全没有实际作用。
修正方案
直接删除针对songStatus的冗余$unwind阶段即可,修正后的聚合代码如下:
countSongStatuses: function (req, res) { db.Event.aggregate([ // 匹配指定Event文档,可直接走_id索引 { $match: { "_id": req.params.id } }, // 仅拆解requestList嵌套数组 { "$unwind": "$requestList" }, // 按songStatus的实际值分组计数 { "$group": { "_id": "$requestList.songStatus", count: { $sum: 1 } } } ]) .then((dbModel) => res.json(dbModel)) .catch((err) => res.status(422).json(err)); },
修正后效果
执行修正后的聚合逻辑,会完全匹配你预期的返回结果:
[ { "_id": "generalRequestQueue", "count": 5 }, { "_id": "playNowQueue", "count": 3 }, { "_id": "queue", "count": 1 } ]
补充说明:如果未来业务调整将songStatus改为数组类型(比如单条请求可关联多个队列状态),再补充对应的songStatus拆解阶段即可,当前的标量字段结构完全不需要额外拆解。
内容的提问来源于stack exchange,提问作者Charles Robinson
相关产品推荐
相关产品推荐

