做多个MongoDB操作的正确方法

如果我需要在less数集合上执行两三个不同的操作,有没有比链接find/update操作更好的方法? 例如:

 db.collection('contactinfos').findOneAndUpdate( { _id: ObjectID(contactID) }, { $set: { sharedWith } } ).then(response => { db.collection('users').update( { _id: { $in: sharedWith.map(id => ObjectID(id)) } }, { $addToSet: { hasAccessTo: contactID } }, { multi: true } ).then(response => { db.collection('users').update( { _id: { $in: notSharedWith.map(id => ObjectID(id)) } }, { $pull: { hasAccessTo: contactID } }, { multi: true } ).then(response => { return res.send({ success: true }); }).catch(err => { logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err); return res.status(400).send({ reason: 'unknown' }); }); }).catch(err => { logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err); return res.status(400).send({ reason: 'unknown' }); }); }).catch(err => { logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err); return res.status(400).send({ reason: 'unknown' }); }); 

这似乎很混乱,必须有一些更好的方式来做到这一点。 此外,如果在第一个findOneAndUpdate之后出现错误,导致其他update无法运行,那么跨文档将存在不一致的数据。 这些文档包含对其他文档的ID引用,以加快查找速度。

另外,有没有办法在承诺链中捕捉到所有错误?

从你的callback地狱,我可以看到你不使用任何地方.then()方法的response参数。 如果您不需要一个查询的结果来执行另一个查询,请考虑使用Promise.all()方法:

 const updateContactInfo = db.collection('contactinfos') .findOneAndUpdate( { _id: ObjectID(contactID) }, { $set: { sharedWith } } ); const updateUsers = db.collection('users') .update( { _id: { $in: sharedWith.map(id => ObjectID(id)) } }, //hint: use .map(ObjectId) instead. { $addToSet: { hasAccessTo: contactID } }, { multi: true } ); const updateUsers2 = db.collection('users') .update( { _id: { $in: notSharedWith.map(id => ObjectID(id)) } }, //hint: use .map(ObjectId) instead. { $pull: { hasAccessTo: contactID } }, { multi: true } ); Promise .all([updateContactInfo, updateUsers, updateUsers2]) .then((values) => { const updateContactInfoResult = values[0]; const updateUsersResult = values[1]; const updateUsers2Result = values[2]; return res.send({ success: true }); }) .catch((reason) => { logger.error(`msg`, reason); return res.status(400).send({ reason: 'unknown' }); }); 

Promise.all()将继续执行Promise.all() .then()只有当所有的promise都解决了,否则它将落入.catch()方法。 从error handling的.catch() ,您可以轻松地链接多个.catch()方法,这在这里很好的解释。

如果您不能有任何数据不一致,则可以:

  1. 用事务获取一些SQL数据库
  2. 研究MongoDB两阶段提交

如果可以接受的话,让我们说每1kk一次,包括检查你的应用程序逻辑中的一致性。