在MongoDB的聚合操作中,$sum是常用的累加运算符,不过不少开发者在用它计算数组内整数之和时,会遇到结果返回0的异常情况,这往往和数据结构、运算符使用方式有关。

常见导致返回0的原因
1. 数组内元素不是数值类型
如果数组中的元素是字符串格式的数字,或者包含非数值类型的元素,$sum无法正确累加,就会返回0。比如文档中的字段值是["1","2","3"],元素都是字符串,直接累加就会出问题。
2. 聚合管道中未正确展开数组
当数组是嵌套在文档中的普通字段时,如果没有先用$unwind展开数组,直接使用$sum操作的是整个数组对象,而不是数组内的单个元素,自然无法得到正确的累加值。
3. $sum的使用位置错误
如果把$sum放在错误的聚合阶段,比如在未处理数组结构的阶段就调用,也会导致无法正确读取数组内的元素进行累加。
对应的解决方法
处理非数值类型的数组元素
如果数组元素是字符串格式的数字,需要先用$toInt或者$convert运算符把元素转换为整数类型,再进行累加。以下是完整的聚合管道示例:
// 假设集合名为test,文档结构为{ _id: 1, scores: ["10", "20", "30"] }
db.test.aggregate([
{
$addFields: {
// 把scores数组内的字符串元素转为整数
scores_int: {
$map: {
input: "$scores",
as: "score",
in: { $toInt: "$$score" }
}
}
}
},
{
$project: {
total: { $sum: "$scores_int" }
}
}
])
正确展开数组后累加
如果数组是普通的一维数组,需要先使用$unwind展开数组,再对展开后的单个元素使用$sum。示例代码如下:
// 假设集合名为test,文档结构为{ _id: 1, scores: [10, 20, 30] }
db.test.aggregate([
{
// 展开scores数组,每个元素生成一条独立文档
$unwind: "$scores"
},
{
$group: {
_id: "$_id",
total: { $sum: "$scores" }
}
}
])
嵌套数组的处理方式
如果数组是嵌套结构,比如{ arr: [ [1,2], [3,4] ] },需要先展开外层数组,再处理内层数组,最后累加。示例代码如下:
db.test.aggregate([
{
$unwind: "$arr"
},
{
$addFields: {
// 对内层数组直接求和
sub_total: { $sum: "$arr" }
}
},
{
$group: {
_id: "$_id",
total: { $sum: "$sub_total" }
}
}
])
验证方法
可以在聚合管道的每个阶段后添加$project阶段,输出中间结果,查看数组转换、展开是否符合预期,逐步定位问题所在。比如先输出转换后的数组,确认元素已经是正确的数值类型,再查看展开后的文档数量是否正确,最后验证累加结果。