我正在使用.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
}
}
);
答案 0 :(得分:2)
主要区别在于,当您使用findById
和save
时,首先要从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/