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

如何在MongoDB中使用聚合操作更新数组值与完成百分比字段

问题解决方案

错误原因

你的写法存在两个核心语法错误:

  1. arrayFilters、multi属于findOneAndUpdate的选项参数,是方法的第三个入参,你错误将其放到了更新操作的聚合管道数组中,导致语法解析失败。
  2. $[element]这类带标识符的数组过滤更新操作符,仅支持普通更新对象场景,不能在聚合更新管道中使用,因此无法和后续计算percentageCompleted的聚合逻辑放在同一个管道数组中。

正确实现方案

我们可以直接在聚合管道中使用$map遍历数组修改指定元素,再同步计算完成率,一次操作完成两个需求,完整代码如下:

db.orders.findOneAndUpdate(
  // 查询条件:匹配指定订单
  { _id: ObjectId('60b114b2415731001943b17f') },
  // 聚合更新管道
  [
    // 第一步:修改指定工序的isCompleted状态
    {
      $set: {
        processList: {
          $map: {
            input: "$processList",
            as: "process",
            in: {
              $cond: [
                // 匹配对应id的工序
                { $eq: ["$$process.id", "60b0f0e9659a3b001c235300"] },
                // 匹配成功则修改isCompleted为true,其余字段保留
                { $mergeObjects: ["$$process", { isCompleted: true }] },
                // 匹配失败则保留原数据
                "$$process"
              ]
            }
          }
        }
      }
    },
    // 第二步:同步计算更新完成百分比(原有逻辑可直接复用)
    {
      $set: {
        percentageCompleted: {
          $multiply: [
            {
              $divide: [
                {
                  $size: {
                    $filter: {
                      input: "$processList",
                      as: "p",
                      cond: { $eq: ["$$p.isCompleted", true] }
                    }
                  }
                },
                { $size: "$processList" }
              ]
            },
            100
          ]
        }
      }
    }
  ],
  // 可选配置:返回更新后的文档
  { returnNewDocument: true }
)

可选方案(使用arrayFilters写法)

如果你更习惯用arrayFilters的写法,可以拆分为两次更新操作,不过性能略低于上面的单次聚合更新方案:

// 第一步:更新指定工序状态
db.orders.updateOne(
  { _id: ObjectId('60b114b2415731001943b17f') },
  { $set: {"processList.$[element].isCompleted": true} },
  { arrayFilters: [{ 'element.id': "60b0f0e9659a3b001c235300" }] }
)
// 第二步:计算更新完成率
db.orders.findOneAndUpdate(
  { _id: ObjectId('60b114b2415731001943b17f') },
  [
    {
      $set: {
        percentageCompleted: {
          $multiply: [
            { $divide: [{ $size: { $filter: { input: "$processList", as: "p", cond: { $eq: ["$$p.isCompleted", true] } } } }, { $size: "$processList" }] },
            100
          ]
        }
      }
    }
  ],
  { returnNewDocument: true }
)

内容的提问来源于stack exchange,提问作者user2453753

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 20:15:03