programing

Mongo DB 4.0 Mongoose & NodeJs와의 트랜잭션, Express

javajsp 2023. 5. 14. 10:21

Mongo DB 4.0 Mongoose & NodeJs와의 트랜잭션, Express

애플리케이션 계층에 Nodejs + Express가 있는 데이터베이스로 MongoDB를 사용하는 애플리케이션을 개발하고 있습니다. 즉, 두 가지 컬렉션이 있습니다.

  1. 사용자들
  2. 거래

여기서 나는 얼마간의 금액으로 수천 명의 사용자들의 지갑을 업데이트해야 하고 성공적으로 각 거래에 대한 관련 정보가 있는 새 문서를 만들어야 합니다. 이것은 내 코드입니다.

 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); 
            }
        });
    }                            
});

하지만 이 해결책은 그렇지 않습니다.atomic사용자 지갑이 금액으로 업데이트될 가능성이 항상 있지만 관련 트랜잭션이 트랜잭션 수집에서 생성되지 않아 재정적 손실이 발생할 수 있습니다.

나는 최근에 그것을 들었습니다.MongoDB추가했습니다.Transactions그것에 대한 지지.4.0 version나는 MongoDB 문서를 읽었지만 Node.js의 mongoose로 성공적으로 구현할 수 없었습니다. 누가 위의 코드가 최신 버전을 사용하여 어떻게 구현되는지 알려줄 수 있습니까?Transactions이러한 기능을 가진 MongoDB의 기능

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

MongoDB 문서: 여기를 클릭합니다.

Node.js의 mongoose와 함께, 누가 위의 코드가 최신 트랜잭션 기능을 사용하여 어떻게 재구현되는지 말해줄 수 있습니까?

mongoose에서 MongoDB 다중 문서 트랜잭션 지원을 사용하려면 v5.2 이상의 버전이 필요합니다.예:

npm install mongoose@5.2

Mongoose 트랜잭션 메서드는 사용해야 하는 세션이 아닌 약속을 반환합니다.await참조:

예를 들어 위의 리소스 및 예제를 변경하면 다음을 시도할 수 있습니다.

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; 
  }
}

원자적이지 않습니다. 사용자 지갑이 금액으로 업데이트될 가능성이 항상 있지만 관련 트랜잭션이 트랜잭션 수집에서 생성되지 않아 재정적 손실이 발생합니다.

또한 MongoDB 데이터 모델을 변경하는 것도 고려해야 합니다.특히 두 컬렉션이 자연스럽게 연결되어 있다면 더욱 그렇습니다.자세한 내용은 원자력 작업에 대한 모형 데이터를 참조하십시오.

시도할 수 있는 예제 모델은 이벤트 소싱 모델입니다.이벤트로 먼저 트랜잭션 항목을 만든 다음 집계를 사용하여 사용자의 지갑 잔액을 다시 계산합니다.

예:

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

그런 다음 요구사항(예: 6시간당)에 따라 각 사용자의 캐시 용량을 계산하는 프로세스를 도입합니다.다음을 추가하여 현재 사용자의 지갑 잔액을 표시할 수 있습니다.

  • 사용자의 마지막 캐시된 양
  • 사용자에 대한 트랜잭션은 마지막으로 캐시된 양(예: 0-6시간 전) 이후에 발생합니다.

언급URL : https://stackoverflow.com/questions/51228059/mongo-db-4-0-transactions-with-mongoose-nodejs-express