Mongo DB 4.0 事务与 Mongoose &NodeJs, Express [英] Mongo DB 4.0 Transactions With Mongoose & NodeJs, Express

查看:26
本文介绍了Mongo DB 4.0 事务与 Mongoose &NodeJs, Express的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,在该应用程序中我使用 MongoDB 作为数据库,在应用程序层使用 Nodejs + Express,我有两个集合,即

  1. 用户
  2. 交易

在这里,我必须用一些金额更新数千名用户的钱包,如果成功为每笔交易创建一个包含相关信息的新文档,这是我的代码:

 userModel.update({_id : ObjectId(userId)}, {$inc : {wallet : 500}}, function (err, creditInfo) {如果(错误){控制台日志(错误);}如果(creditInfo.nModified > 0){newTransModel = 新的transModel({用户 ID:对象 ID(用户 ID),金额:winAmt,类型:'信用',});newTransModel.save(function (err, doc) {如果(错误){Cb(错误);}});}});

但这个解决方案不是原子总是有可能用户钱包更新了金额,但相关交易未在交易集合中创建,从而导致财务损失.

我听说最近 MongoDB 在其 4.0 版本 中添加了 Transactions 支持,我已经阅读了 MongoDB 文档但无法获得它成功实现它在 Node.js 中使用 mongoose,谁能告诉我如何使用具有这些功能的 MongoDB 的最新 Transactions 功能重新实现上面的代码

Session.startTransaction()Session.abortTransaction()Session.commitTransaction()

MongoDB 文档:点击此处

解决方案

在 Node.js 中使用 mongoose,谁能告诉我如何使用最新的交易功能重新实现上面的代码

MongoDB多文档事务支持://mongoosejs.com/docs/guide.html" rel="noreferrer">mongoose 你需要高于 v5.2 的版本.例如:

npm install mongoose@5.2

Mongoose 事务方法返回一个承诺而不是需要使用 await 的会话.见:

例如,更改上面资源中的示例和您的示例,您可以尝试:

const User = mongoose.model('Users', new mongoose.Schema({用户 ID:字符串,钱包:数字}));const Transaction = mongoose.model('Transactions', new mongoose.Schema({用户 ID:对象 ID,数量:数字,类型:字符串}));等待更新钱包(用户 ID,500);异步函数 updateWallet(userId, amount) {const session = await User.startSession();session.startTransaction();尝试 {const opts = { session };const A = await User.findOneAndUpdate({ _id: userId }, { $inc: { wallet: amount } }, opts);const B = 等待交易({ usersId:userId,金额:金额,类型:信用"}).保存(选择);等待 session.commitTransaction();session.endSession();返回真;} 捕捉(错误){//如果发生错误,则中止整个事务并//撤消任何可能发生的更改等待 session.abortTransaction();session.endSession();抛出错误;}}

<块引用>

不是原子的,总是有可能用户钱包更新了金额但相关交易未在交易集合中创建导致财务损失

您还应该考虑更改 MongoDB 数据模型.特别是如果这两个集合是自然连接的.另请参阅原子操作的模型数据了解更多信息.

您可以尝试的一个示例模型是事件溯源模型.首先创建一个交易条目作为事件,然后使用 aggregation 重新计算用户的钱包余额.

例如:

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

然后引入一个流程,根据需求(即每 6 小时)计算每个时期每个用户的数量作为缓存.可以通过添加来显示当前用户的钱包余额:

  • 用户最后一次缓存的数量
  • 自上次缓存金额以来发生的任何用户交易.即 0-6 小时前.

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. transactions

Here i have to update wallet of thousands of users with some amount and if successful create a new document with related info for each transaction, This is My code :

 userModel.update({_id : ObjectId(userId)}, {$inc : {wallet : 500}}, function (err, creditInfo) {
    if(err){
        console.log(err);                            
    }
    if(creditInfo.nModified > 0) {
        newTransModel = new transModel({
            usersId: ObjectId(userId),            
            amount: winAmt,         
            type: 'credit',           
        }); 
        newTransModel.save(function (err, doc) {
            if(err){
                Cb(err); 
            }
        });
    }                            
});

but this solution 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.

I have heard that recently MongoDB has added Transactions support in its 4.0 version, I have read the MongoDB docs but couldn't get it to successfully implement it with mongoose in Node.js, can anyone tell me how this above code be reimplemented using the latest Transactions feature of MongoDB which have these functions

Session.startTransaction()
Session.abortTransaction()
Session.commitTransaction()

MongoDB Docs : Click Here

解决方案

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:

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.

这篇关于Mongo DB 4.0 事务与 Mongoose &amp;NodeJs, Express的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆