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

时间:2019-01-22 12:42:29

标签: node.js mongoose

我正在使用.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);
    });
};

我认为他们在说什么,但应该这样做(我在Google之后找到一个例子)

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

1 个答案:

答案 0 :(得分:2)

主要区别在于,当您使用findByIdsave时,首先要从MongoDB获取对象,然后再更新所需的内容然后保存。当您不必担心并行性或对同一对象的多个查询时,可以这样做。

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

但是,假设您在对象上有一个计数器,例如friendsTotal,起始值为0。并且您击中了必须为同一对象将计数器增加一倍的端点。

如果使用findById,然后先增大然后save,则由于设置了整个值,您会遇到一些问题。因此,您首先获取对象,将其增加到1,然后更新。但是其他要求也一样。您将得到friendsTotal = 1

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

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