You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:47:17