在MongoDB中将$ addFields用作更新功能的一部分

时间:2018-10-30 20:21:12

标签: mongodb mongoose aggregation-framework

我试图弄清楚如何在用于更新文档的函数中使用$addFields操作。生成该字段的逻辑非常简单,我只需拔出数组中的最后一个对象,如下所示:

  {
    $addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } }
  }

现在,我需要弄清楚如何将这种聚合纳入更新功能,其相关代码如下所示:

updatedDoc = await request.findOneAndUpdate(
  StaffMember,
  {
    _id: request.parameters.id
  },
  req,
  {
    new: true
  }
);

我试图做的是这样:

updatedDoc = await request.findOneAndUpdate(
  StaffMember,
  {
    _id: request.parameters.id
  },
  req,
  {
    new: true
  }
);

await request.aggregate(updatedDoc, [
  {
    $addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } }
  }
]);

...但是这给了我一个错误:

  

TypeError:mongooseModelObject.aggregate不是函数

我会和$ set一起使用$ addFields运算符吗?

updatedDoc = await request.findOneAndUpdate(
      StaffMember,
      {
        _id: request.parameters.id
      },
      {
        $set: {
          req,
          $addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } }
        }
      },
      {
        new: true
      }
    );

如何将聚合作为此类函数的一部分运行?一个简单的示例将帮助我理解该如何完成-如果确实可以完成。

当然,还有其他方法可以执行此操作,但是我想利用像$addFields这样的mongo操作来利用mongo特定的方法来处理此问题。会是什么样?

顺便说一句,我与聚合一起使用的包装函数看起来像这样:

  async aggregate(mongooseModelObject, aggregateObject = {}) {
    try {
      return await mongooseModelObject.aggregate(aggregateObject).exec();
    } catch (err) {
      this.sendError(err);
    }
  }

2 个答案:

答案 0 :(得分:2)

基本上,您不能使用aggregate作为更新的一部分。使用$addFields更新数据的唯一方法是像这样使用$out

db.col.aggregate([
    {  $addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } } },
    {  $out: "col" }
])

但是很遗憾,这将为activeWorkflow中的所有文档添加col

对于常规.update(),您无法引用其他字段,因此对单个文档执行此操作的唯一方法是使用findOne()获取该文档,然后在应用程序逻辑中添加新字段,并然后使用update()save()存储该更新的文档(旧问题here)。

答案 1 :(得分:0)

从 MongoDB 4.2 开始,findAndUpdateOneupdateOneupdateMany 可以接受 aggregation pipeline 进行更新。

const updatedDocument = await DocumentModel.updateOne({ _id: id }, [
  {
     $set: {
       items: items,
     }
  },
  {
     $addFields: { totalItems: { $sum: '$items.quantity' } },
  }
 ],
 { new: true } // to return updated document
);