Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't you modify the data returned by a Mongoose Query (ex: findById)

When I try to change any part of the data returned by a Mongoose Query it has no effect.

I was trying to figure this out for about 2 hours yesterday, with all kinds of _.clone()s, using temporary storage variables, etc. Finally, just when I though I was going crazy, I found a solution. So I figured somebody in the future (fyuuuture!) might have the save issue.

Survey.findById(req.params.id, function(err, data){     var len = data.survey_questions.length;     var counter = 0;      _.each(data.survey_questions, function(sq){         Question.findById(sq.question, function(err, q){             sq.question = q; //has no effect              if(++counter == len) {                 res.send(data);             }         });     }); }); 
like image 910
Toli Avatar asked Jan 24 '13 15:01

Toli


People also ask

What does findById return Mongoose?

Return value findById returns the document where the _id field matches the specified id . If the document is not found, the function returns null .

What is findById in Mongoose?

Mongoose | findById() Function The findById() function is used to find a single document by its _id field. The _id field is cast based on the Schema before sending the command. Installation of mongoose module: You can visit the link Install mongoose module. You can install this package by using this command.

What does Mongoose Exec return?

exec() function returns a promise, that you can use it with then() or async/await to execute a query on a model "asynchronous".

Does Mongoose save overwrite?

Mongoose save with an existing document will not override the same object reference. Bookmark this question.


2 Answers

For cases like this where you want a plain JS object instead of a full model instance, you can call lean() on the query chain like so:

Survey.findById(req.params.id).lean().exec(function(err, data){     var len = data.survey_questions.length;     var counter = 0;      _.each(data.survey_questions, function(sq){         Question.findById(sq.question, function(err, q){             sq.question = q;              if(++counter == len) {                 res.send(data);             }         });     }); }); 

This way data is already a plain JS object you can manipulate as you need to.

like image 123
JohnnyHK Avatar answered Sep 28 '22 11:09

JohnnyHK


I think the Mongoose documentation doesn't make this clear enough, but the data returned in the query (although you can res.send() it) is actually a Mongoose Document object, and NOT a JSON object. But you can fix this with one line...

Survey.findById(req.params.id, function(err, data){     var len = data.survey_questions.length;     var counter = 0;      var data = data.toJSON(); //turns it into JSON YAY!      _.each(data.survey_questions, function(sq){         Question.findById(sq.question, function(err, q){             sq.question = q;              if(++counter == len) {                 res.send(data);             }         });     }); }); 
like image 34
Toli Avatar answered Sep 28 '22 09:09

Toli