如何用JavaScript和mongojs将单文档插入两个MongoDB集合?
解决mongojs同时插入多个MongoDB集合的问题
你之前尝试的(db.completeds&&db.deliveredhistory)insert(data)写法是行不通的——因为mongojs的集合insert是异步操作,每个集合的插入都需要单独调用并处理其执行结果。下面给你两种实用的解决方案:
方案1:回调嵌套(简单直接)
在第一个集合插入成功的回调里,再执行第二个集合的插入,等两个操作都完成后再返回响应。同时要做好每一步的错误处理:
function route(app){ app.post('/shipper/completed',function(req, res){ var item_id = req.body.item_id var id = mongojs.ObjectId(item_id); db.delivereds.findAndModify({ "query":{ "_id": id }, "remove": false }, function(err, data) { if (err) { return res.json({ status:400, message:"Failed to fetch delivery data", err:err }) } if (!data) { console.log("fake number") return res.json({ status: 403, message:'This load is not available for accepting' }) } // 先插入completeds集合 db.completeds.insert(data, function(err, completedResult) { if (err) { return res.json({ status:400, message:"Failed to mark as complete", err:err }) } // 再插入deliveredhistory集合 db.deliveredhistory.insert(data, function(err, historyResult) { if (err) { return res.json({ status:400, message:"Failed to record delivery history", err:err }) } // 两个插入都成功,返回最终响应 res.json({ status:200, message:"Job successfully completed and history saved", completedData: completedResult, historyData: historyResult }); }) }) }) }) }
方案2:Promise并行处理(优雅避免回调地狱)
把mongojs的异步方法包装成Promise,再用Promise.all并行执行两个插入操作,代码结构会更清晰:
// 封装一个Promise版的插入方法 function insertToCollection(collection, data) { return new Promise((resolve, reject) => { collection.insert(data, (err, result) => { err ? reject(err) : resolve(result); }) }) } // 同样给findAndModify封装Promise function findAndModify(collection, queryOpts) { return new Promise((resolve, reject) => { collection.findAndModify(queryOpts, (err, data) => { err ? reject(err) : resolve(data); }) }) } function route(app){ app.post('/shipper/completed', async function(req, res){ try { var item_id = req.body.item_id var id = mongojs.ObjectId(item_id); // 获取目标数据 const data = await findAndModify(db.delivereds, { "query":{ "_id": id }, "remove": false }) if (!data) { console.log("fake number") return res.json({ status: 403, message:'This load is not available for accepting' }) } // 并行执行两个插入操作 const [completedResult, historyResult] = await Promise.all([ insertToCollection(db.completeds, data), insertToCollection(db.deliveredhistory, data) ]) // 全部成功后返回响应 res.json({ status:200, message:"Job successfully completed and history recorded", completedData: completedResult, historyData: historyResult }); } catch (err) { // 统一捕获所有错误 res.json({ status:400, message:"Operation failed", err:err }) } }) }
额外提醒
如果需要强原子性(两个插入要么都成功,要么都失败),mongojs本身不支持跨集合事务,这时候你需要使用MongoDB 4.0+的事务功能(要求副本集部署),不过大部分场景下上面的方案已经足够满足需求。
内容的提问来源于stack exchange,提问作者Swam Didam
相关产品推荐
相关产品推荐

