0

Inside a Node Route, I'm saving two documents, both of different models, but instead of getting saved in the order in the code (via top-down approach), they are getting saved in reverse order.

modelOneDoc.save().then((doc) => console.log('Model One Document saved'));
modelTwoDoc.save().then((doc) => console.log('Model Two Document saved'));

Output:

Model Two Document saved
Model One Document saved

Both Of the Model's Schema has a pre save call attached that does some calculation before saving the document. And I think that Its the pre calls that is disturbing the saving order.

Saving of ModelOneDoc before ModelTwoDoc is essential because ModelTwoDoc fetches ModelOneDoc in its pre save call. Help me solve the problem.

GitHub Repo here (Route: /exam/submit/:id)

EDIT: The Code Snippet is as follows:

request.body.questionAnswers.forEach((element, index) => {
        var questionAnswer = new QuestionAnswer({exam: id});
        examReturn.questionAnswers.push(questionAnswer._id);
        questionAnswer.save().catch((error) => console.log(error));
    });

    examReturn.save().then(() => response.send('Exam Successfully submitted in Store'), (error) => response.status(400).send(error));

I have the First save call inside a loop, i expected that Second call (examReturn.save()) will be done after all the documents in the loop have been stored.

I cannot use the solution of nesting the model saving inside then calls here, as the Second model will be saved in first then call of loped documents.

Sorry for providing insufficient data earlier.

Himanshu Mittal
  • 584
  • 1
  • 6
  • 21
  • That's sound about right as both operations are [asynchronous](https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean). If you want the second document to be saved after the first, you need to replace the first `console.log` with the second line. – Mikey Sep 28 '17 at 13:39
  • I suppose that the saving function is async, so you can try to save the second document inner the first `then` like this `modelOne.save().then(function(doc) { modelTwo.save() })` – Federico B. Sep 28 '17 at 13:41
  • @Mikey can you help me in above problem? – Himanshu Mittal Sep 28 '17 at 13:58

2 Answers2

1

The simpliest way of doing your problem is to use Model.create to create all your answers first, then push the newly-created document references into the exam, and save the exam. So you end up doing only 2 queries.

var answers = request.body.questionAnswers.map(answer => {
    return { exam: id };
});

// create QuestionAnswer documents
QuestionAnswer.create(answers, (err, answers) => {
    if (err)
        return response.status(400).send(err);
    // push references
    answers.forEach(answer => {
         examReturn.questionAnswers.push(answer._id);
    });
    // save exam
    examReturn.save(err => {
        if (err)
            return response.status(400).send(err);
        response.send('Exam Successfully submitted in Store');
    });
});
Mikey
  • 6,728
  • 4
  • 22
  • 45
0

If the save function is asynchronous, you must save the second model in the function of the first then:

modelOneDoc.save().then(function(doc) {
    console.log('Model One Document saved')
    modelTwoDoc.save().then(function(doc) {console.log('Model Two Document saved')})
})

In this way the second model will be saved after the first model.

Federico B.
  • 189
  • 4