MongoDB聚合$sum无法求和嵌套nutrients字段问题咨询
问题
我的配料文档包含嵌套的nutrients字段,结构示例如下:
nutrients: { vitaminB: { type: Number, default: 0, }, vitaminC: { type: Number, default: 0, }, // 更多营养成分字段 }
我使用以下MongoDB聚合代码尝试对营养成分求和:
Ingredient.aggregate([ { $match: { _id: { $in: ingredientIds } }, }, { $group: { _id: null, sums: { $sum: '$nutrients' }, }, }, ]); console.log(stats[0].sums);
执行后输出结果为0,但单独指定嵌套字段(如$nutrients.vitaminC)时能正常求和。我期望sums是包含所有营养成分字段求和结果的对象。
原因
MongoDB的$sum操作符仅支持对数值类型字段求和。当传入$nutrients(对象类型)时,MongoDB会将其隐式转换为数值,对象转数值的结果为0,因此最终求和结果为0。
解决方案
根据nutrients字段是否固定,可采用两种处理方式:
方式1:已知所有营养成分字段
若提前明确nutrients下的所有字段,可在$group阶段逐个字段求和,再组合成目标对象:
Ingredient.aggregate([ { $match: { _id: { $in: ingredientIds } } }, { $group: { _id: null, vitaminB: { $sum: '$nutrients.vitaminB' }, vitaminC: { $sum: '$nutrients.vitaminC' }, // 依次添加其他营养成分字段 } }, { $project: { _id: 0, sums: { vitaminB: '$vitaminB', vitaminC: '$vitaminC', // 对应上述分组的字段 } } } ]);
方式2:动态处理未知字段
若nutrients下的字段是动态不确定的,可通过对象与数组的转换实现批量求和:
Ingredient.aggregate([ { $match: { _id: { $in: ingredientIds } } }, // 将nutrients对象转为[{k: "vitaminB", v: 值}, ...]格式的数组 { $project: { nutrients: { $objectToArray: '$nutrients' } } }, // 展开数组,让每个营养成分单独成为一条文档 { $unwind: '$nutrients' }, // 按营养成分名称分组求和 { $group: { _id: '$nutrients.k', total: { $sum: '$nutrients.v' } } }, // 转换为{k: 名称, v: 总和}格式的文档 { $project: { k: '$_id', v: '$total', _id: 0 } }, // 将数组转回对象,并包裹到sums字段中 { $group: { _id: null, sums: { $arrayToObject: '$$ROOT' } } }, { $project: { _id: 0 } } ]);
内容的提问来源于stack exchange,提问作者jorge silva
相关产品推荐
相关产品推荐

