【问题标题】:Mongoose multiple dependant queriesMongoose 多个依赖查询
【发布时间】:2020-12-14 23:39:52
【问题描述】:

我正在尝试将一个新文档保存到一个集合中,并同时更新两个不同集合中的另外两个文档,如下所示:

const newApplication = new ApplicationSchema({...})
newApplication.save()

EventSchema.findByIdAndUpdate(event_id, { $inc: { "application_counts": 1 } })

EventOwnerSchema.findByIdAndUpdate(event_owner_id, { $dec: { "balance": ticketPrice } })

这些操作是相互关联的,如果其中任何一个失败,我想让它们都失败。如果其中任何一步失败,一种可能的解决方案可能是链接它们并恢复以前的更新。

const newApplication = new ApplicationSchema({...})
newApplication.save((err, res_1) => {
  if(err) {
    return false;
  }
  EventSchema.findByIdAndUpdate(event_id, { $inc: { "application_counts": 1 } }, (err, res_2) => {
    if(err) {
      ApplicationSchema.deleteOne({_id: res_1._id})
      return false;
    }
    EventOwnerSchema.findByIdAndUpdate(event_owner_id, { $dec: { "balance": ticketPrice } }, (err, res_3) => {
      if(err) {
        ApplicationSchema.deleteOne({_id: res_1._id})
        EventSchema.findByIdAndUpdate(event_id, { $dec: { "application_counts": 1 } })
        return false;
      }
      return true;
    })
  })
})

但是,这个解决方案在性能方面看起来并不理想(同样出于同样的原因,这个问题存在,但我猜我太挑剔了)。有什么建议吗?

编辑: 脚注:出于其他原因,我没有使用嵌入式文档。

【问题讨论】:

  • 如果您考虑它并且过于挑剔,如果失败了,那么您必须将更新的文档恢复到其原始状态,但您还必须考虑在恢复它的过程中,您检查它是失败还是成功。我的意思是,这将是一个永无止境的循环。我建议你选择一种典型和传统的方式。
  • 你应该看看Mongoose transactions
  • @ThomasBormans 谢谢,这正是我要找的。​​span>

标签: node.js mongodb mongoose


【解决方案1】:

事务就是为此而生的。 Mongoose Transactions

它允许您创建会话、执行某些操作并中止/提交您在会话中所做的更改。

const mongoose = require("mongoose");

// Start the session
const session = await mongoose.startSession();
session.startTransaction();

try {
    // Perform queries
    const newApplication = new ApplicationSchema({...})
    const p1 = newApplication .save();
    const p2 = EventSchema.findByIdAndUpdate(event_id, { $inc: { "application_counts": 1 } })
    const p3 = EventOwnerSchema.findByIdAndUpdate(event_owner_id, { $dec: { "balance": ticketPrice } })

    // Wait for the results
    const values = await Promise.all([p1, p2, p3]);

    // If did not throw any errors, commit changes and resolve
    await session.commitTransaction();
    resolve(values);
} catch (err) {
    // If an error occured, abort all changes and reject
    await session.abortTransaction();
    reject(err);
}

感谢@Thomas Bormans的评论

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多