如何在MongoDB的findOneAndUpdate中区分插入/更新修改文档
解决方案
你可以利用MongoDB的聚合表达式操作符($cond、$add、$exists)来区分插入和更新场景,实现需求。同时要修正原代码中then方法的调用问题(原写法会提前发送响应)。修改后的代码如下:
upsert = (req, res) => { return Promise.all(req.body.map(resource => { return Resource.findOneAndUpdate( { resource_id: resource.id }, { $set: { title: resource.title, seller_id: resource.seller_id, initial_quantity: resource.quantity, // 核心逻辑:判断是否为新插入文档,设置对应quantity值 quantity: { $cond: { if: { $exists: ["$quantity", true] }, // 存在quantity字段说明是更新操作 then: { $add: ["$quantity", resource.quantity] }, // 更新时累加传入的数量 else: 0 // 插入时设置为0 } } } }, { upsert: true, new: true } ); })) .then(() => { // 修正:在回调内发送响应,确保Promise完成后执行 res.status(200).json({ message: "OK" }); }) .catch(err => { console.log(err); res.status(500).json({ message: "Error" }); }); }
关键逻辑说明
$exists: ["$quantity", true]:判断当前文档是否存在quantity字段,新插入的文档不存在该字段,因此会触发else分支设为0;已有文档存在该字段,触发then分支执行累加。$add: ["$quantity", resource.quantity]:将数据库中原有quantity值与请求传入的数量相加,实现更新时的累加需求。- 修正
then的调用方式:原代码直接执行res.status(200).json(...)会导致在Promise.all未完成时就发送响应,改为在回调函数内执行,确保所有数据库操作完成后再返回结果。
注意事项
- 该方案依赖MongoDB 3.6及以上版本,因为需要支持在更新操作中使用聚合表达式。
- 确保
resource.quantity是数值类型,避免加法操作出现异常。
内容的提问来源于stack exchange,提问作者Luis Urán
相关产品推荐
相关产品推荐

