mit Mongoose in Node.js, kann mir jemand sagen, wie dieser obige Code mit der neuesten Transaktionsfunktion
neu implementiert werden kannUm die MongoDB-Unterstützung für Transaktionen mit mehreren Dokumenten in Mongoose zu verwenden, benötigen Sie eine Version größer als v5.2. Zum Beispiel:
npm install [email protected]
Mongoose-Transaktionsmethoden geben eher ein Versprechen als eine Sitzung zurück, die die Verwendung von await
erfordern würde . Siehe:
- Transaktionen in Mongoose
- Blog:Eine Node.JS-Perspektive zu MongoDB 4.0:Transaktionen
Wenn Sie beispielsweise das Beispiel in der obigen Ressource und Ihr Beispiel ändern, können Sie Folgendes versuchen:
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;
}
}
ist nicht atomar, es besteht immer die Möglichkeit, dass die Benutzer-Brieftasche mit dem Betrag aktualisiert wird, aber die zugehörige Transaktion nicht in der Transaktionssammlung erstellt wird, was zu finanziellen Verlusten führt
Sie sollten auch erwägen, Ihre MongoDB-Datenmodelle zu ändern. Vor allem, wenn die beiden Sammlungen natürlich miteinander verbunden sind. Siehe auch Modelldaten für atomare Operationen für weitere Informationen.
Ein Beispielmodell, das Sie ausprobieren könnten, ist das Event-Sourcing-Modell. Erstellen Sie zuerst einen Transaktionseintrag als Ereignis und berechnen Sie dann das Wallet-Guthaben des Benutzers mithilfe der Aggregation neu.
Zum Beispiel:
{tranId: 1001, fromUser:800, toUser:99, amount:300, time: Date(..)}
{tranId: 1002, fromUser:77, toUser:99, amount:100, time: Date(..)}
Führen Sie dann einen Prozess ein, um die Menge für jeden Benutzer pro Zeitraum als Cache je nach Bedarf (dh pro 6 Stunden) zu berechnen. Sie können das Wallet-Guthaben des aktuellen Benutzers anzeigen, indem Sie Folgendes hinzufügen:
- Der letzte zwischengespeicherte Betrag für den Benutzer
- Alle Transaktionen für den Benutzer finden seit dem letzten zwischengespeicherten Betrag statt. d.h. vor 0-6 Stunden.