I'm trying to insert multiple documents with mongoose on a MongoDB database, but I have some problems when trying to synchronize two middlewares. Let me explain the flow:
- An array of documents [A] is passed, and I need to insert them all inside collection [A]
- Each document from [A], when inserted, has to create multiple documents [B] (from one to three) inside another collection [B]
- Each [B] document has to update informations inside a document [C] in another collection [C].
- When all these tasks are finished, I can go on with the second [A] document, ad so on...
In my code, I structured this with one .pre "save" middleware on the [A] documents, and a .pre "save" middleware on the [B] documents.
I tried with ".insertMany()", but I need to run these middlewares on a single document .save() too.
Here is the code for looping through all the documents of the array [A], called "data", and save the document inside its collection.:
data.forEach(async (transaction) => {
const document = new Transaction({
date: transaction.date,
amount: transaction.amount,
type: transaction.type,
});
await document.save();
});
I use await because I want to wait the save of this document before going on the second one. So, with a .pre "save" middleware, I can create the [B] documents before going on the second [A] document.
TransactionSchema.pre("save", async function (next) {
const allTransactions = this.model("AllTransactions");
var amount = Math.abs(this.amount);
switch (this.type) {
case "A":
const A_Transaction = new allTransactions({
transaction_id: this._id,
amount: amount,
date: this.date,
type: "A",
});
await A_Transaction.save();
break;
case "B":
// ...
break;
case "C":
// ...
break;
}
next();
});
With the same logic, I create the [B] document (in this case only one document) with await .save(), so I can us a second middleware on a .pre save() to update the documents in the third collection.
AllTransactionsSchema.pre("save", function (next) {
const Data = this.model("Data");
const DataToUpdate = Data.findById(//data id);
DataToUpdate.then(async (instance) => {
instance.values.forEach(async (value) => {
//operations
await instance.save();
});
});
next();
});
The problem is, the second document of the [A] array is inserted before the end of the execution of all middlewares. I used async await on all .save(), but it's like it isn't working.
I'm trying to figure out how to synchronize all these operations, one by one; I'm still a student on MongoDB and noSQL.
Thanks!
CodePudding user response:
Replace forEach with a normal loop. JavaScripts' higher order array functions do not actually wait when await is placed inside, instead they just fire off multiple async calls.
EDIT:
Added an example
const fireTransactions = async () => {
for (const transaction of data) {
const document = new Transaction({
date: transaction.date,
amount: transaction.amount,
type: transaction.type,
});
await document.save();
}
}