Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to properly async the MongoDB .save() with mongoose?

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:

  1. An array of documents [A] is passed, and I need to insert them all inside collection [A]
  2. Each document from [A], when inserted, has to create multiple documents [B] (from one to three) inside another collection [B]
  3. Each [B] document has to update informations inside a document [C] in another collection [C].
  4. 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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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!

>Solution :

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();
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading