使用 .save() 与 findByIdAndUpdate() 从数组中删除项目

use*_*989 3 mongoose node.js

我正在使用.pull从 mongo db 中的数组中删除记录并且它工作正常,但是我在堆栈溢出的某处读到的评论(无法再次找到它来发布链接)困扰着我,因为它评论说它很糟糕使用.save而不是使用.findByIdAndUpdate.updateOne

我只是想知道这是准确的还是主观的。

这就是我目前的做法。我检查具有该 id 的产品是否确实存在,如果存在,我从数组中提取该记录。

exports.deleteImg = (req, res, next) => {
  const productId = req.params.productId;
  const imgId = req.params.imgId;
  Product.findById(productId)
    .then(product => {
      if (!product) {
        return res.status(500).json({ message: "Product not found" });
      } else {
        product.images.pull(imgId);
        product.save()
        .then(response => {
          return res.status(200).json( { message: 'Image deleted'} );
        })
      }
    })
    .catch(err => {
      console.log(err);
    });
};
Run Code Online (Sandbox Code Playgroud)

我认为他们所说的应该是做这样的事情(我在谷歌之后找到的一个例子)

users.findByIdAndUpdate(userID,
    {$pull: {friends: friend}},
    {safe: true, upsert: true},
    function(err, doc) {
        if(err){
        console.log(err);
        }else{
        //do stuff
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

小智 6

主要区别在于,当您使用findByIdand 时save,您首先从 MongoDB 获取对象,然后更新您想要的任何内容,然后保存。当您不需要担心对同一对象的并行性或多个查询时,这是可以的。

findByIdAndUpdate是原子的。当您多次执行此操作时,MongoDB 会为您处理并行性。按照您的示例,如果在同一个对象上同时发出两个请求,通过{ $pull: { friends: friendId } },结果将是预期的:只会从数组中拉出一个朋友。

但是,假设您在对象上有一个计数器,例如friendsTotal起始值为 0。并且您遇到了必须将计数器加 1 两次的端点,对于同一个对象。

如果您使用findById,然后增加然后save,您会遇到一些问题,因为您正在设置整个值。所以,你首先得到对象,增加到 1,然后更新。但另一个请求也做了同样的事情。你最终会得到friendsTotal = 1.

随着findByIdAndUpdate你可以使用{ $inc: { friendsTotal: 1 } }. 因此,即使您对同一对象同时执行两次此查询,最终也会得到friendsTotal = 2,因为 MongoDB 使用这些更新运算符来更好地处理并行性、数据锁定等。

$inc在此处查看更多信息:https : //docs.mongodb.com/manual/reference/operator/update/inc/