Mongo DB 4.0 Transactions With Mongoose & NodeJs, Express

后端 未结 1 694
情歌与酒
情歌与酒 2021-01-30 11:35

I am developing an application where I am using MongoDB as database with Nodejs + Express in application layer, I have two collections, namely

  1. users
  2. tran
相关标签:
1条回答
  • 2021-01-30 12:06

    with mongoose in Node.js, can anyone tell me how this above code be reimplemented using the latest Transactions feature

    To use MongoDB multi-documents transactions support in mongoose you need version greater than v5.2. For example:

    npm install mongoose@5.2
    

    Mongoose transactional methods returns a promise rather than a session which would require to use await. See:

    • Transactions in Mongoose
    • Blog: A Node.JS Perspective on MongoDB 4.0: Transactions

    For example, altering the example on the resource above and your example, you can try:

    const User = mongoose.model('Users', new mongoose.Schema({
      userId: String, wallet: Number
    }));
    const Transaction = mongoose.model('Transactions', new mongoose.Schema({
      userId: ObjectId, amount: Number, type: String
    }));
    
    await updateWallet(userId, 500);
    
    async function updateWallet(userId, amount) {
      const session = await User.startSession();
      session.startTransaction();
      try {
        const opts = { session };
        const A = await User.findOneAndUpdate(
                        { _id: userId }, { $inc: { wallet: amount } }, opts);
    
        const B = await Transaction(
                        { usersId: userId, amount: amount, type: "credit" })
                        .save(opts);
    
        await session.commitTransaction();
        session.endSession();
        return true;
      } catch (error) {
        // If an error occurred, abort the whole transaction and
        // undo any changes that might have happened
        await session.abortTransaction();
        session.endSession();
        throw error; 
      }
    }
    

    is not atomic there is always a possibility of user wallet updated with amount but related transaction not created in transactions collection resulting in financial loss

    You should also consider changing your MongoDB data models. Especially if the two collections are naturally linked. See also Model data for Atomic Operations for more information.

    An example model that you could try is Event Sourcing model. Create a transaction entry first as an event, then recalculate the user's wallet balance using aggregation.

    For example:

    {tranId: 1001, fromUser:800, toUser:99, amount:300, time: Date(..)}
    {tranId: 1002, fromUser:77, toUser:99, amount:100, time: Date(..)}
    

    Then introduce a process to calculate the amount for each users per period as a cache depending on requirements (i.e. per 6 hours). You can display the current user's wallet balance by adding:

    • The last cached amount for the user
    • Any transactions for the user occur since the last cached amount. i.e. 0-6 hours ago.
    0 讨论(0)
提交回复
热议问题