Mongo DB 4.0 Операции с Mongoose & NodeJs, Express

Gaurav Kumar спросил: 13 июня 2018 в 11:17 в: node.js

Я разрабатываю приложение, в котором я использую MongoDB как базу данных с Nodejs + Express в прикладном уровне, у меня есть две коллекции, а именно

  1. users
  2. transaction

Здесь я должен обновить кошелек тысяч пользователей с некоторой суммой и, если успешно, создать новый документ с соответствующей информацией для каждой транзакции, это мой код:

 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, но не смог его получить успешно реализовать его с помощью mongoose в Node.js, может ли кто-нибудь сказать мне, как этот вышеперечисленный код переопределяется с использованием последней функции Transactions MongoDB, которая имеет эти функции

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

Документы MongoDB: Нажмите здесь

1 ответ

Есть решение
Wan Bachtiar ответил: 16 июня 2018 в 06:16

с mongoose в Node.js, может ли кто-нибудь сказать мне, как этот вышеприведенный код будет переопределен с использованием последней функции транзакций.

Чтобы использовать транзакцию транзакций Multi-documents MongoDB в мангусте, вы нужна версия больше v5.2. Например:

npm install mongoose@5.2

Методы транзакций Mongoose возвращают обещание, а не сеанс, который потребует использования await. См .:

  • Транзакции в Mongoose
  • Блог: перспектива Node.JS на MongoDB 4.0: транзакции

Например, изменение пример на ресурсе выше и в вашем примере, вы можете попробовать:

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. Особенно, если две коллекции естественно связаны. Дополнительные сведения см. В разделе "Данные модели для Atomic Operations".

Примерной моделью, которую вы можете попробовать, является модель Event Sourcing. Создайте запись транзакции сначала как событие, затем пересчитайте баланс пользователя с помощью агрегации.

Например:

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

Затем введите процесс вычисления суммы для каждого пользователя за период в виде кеша в зависимости от требований (т.е. в течение 6 часов). Вы можете отобразить баланс кошелька текущего пользователя, добавив:

  • Последняя кэшированная сумма для пользователя
  • Любые транзакции для пользователя происходят со времени последней кэшированной суммы. то есть 0-6 часов назад.
Gaurav Kumar ответил: 15 июня 2018 в 03:01
есть две вещи об этом: 1) ждать updateWallet (userId, 500); & Л; & л; & л; это приводит к ошибке, говорящей, что ожидание должно быть в async-функции, ожидающий верхнего уровня не допускается 2), поскольку я делаю это в цикле async eachseries i.e, обновляя многие кошельки пользователей, я получаю исправленную ошибку транзакций & когда я вызываю следующую итерацию, также используя блок finally после попытки catch также не работает
Gaurav Kumar ответил: 15 июня 2018 в 12:50
спасибо за помощь, я уже успешно реализовал это, вторая ошибка была моей ошибкой кодирования, а не проблемой кода.
Wan Bachtiar ответил: 15 июня 2018 в 11:26
Это пример, вам придется приспособиться к своему собственному прецеденту. 1) Убедитесь, что вы создали асинхронную функцию, как показано выше. 2) Вместо этого вы можете попробовать выполнить функцию bulkWrite ().
Gaurav Kumar ответил: 15 июня 2018 в 12:51
просто отредактируйте свой ответ и отредактируйте этот > > > > User.db.startSession (); к Mymodel.startSession () ........ он говорит, что db не определено, мы можем использовать любую модель mongoose для запуска сеанса, который не был привязан к той модели, которая была создана после создания.
Wan Bachtiar ответил: 16 июня 2018 в 06:17
Ах да, я пытался сделать акцент на том, что сеанс для базы данных не по коллекции, но сделал ошибку. Исправлено. Благодарю.

Дополнительное видео по вопросу: Mongo DB 4.0 Операции с Mongoose & NodeJs, Express

MongoDB and Mongoose | Creating a REST API with Node.js

Node.js & Express From Scratch [Part 4] - Mongoose & Model Setup

MongoDB Full Tutorial w/ Node.js, Express, & Mongoose