kumarD
kumarD

Reputation: 594

How to save the Object returned from the query.exec() function in mongoose

I am new to mongoose. Here is my scenario:

var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
children: [childSchema]});
var Parent = mongoose.model('Parent', parentSchema);

Say I have created a parent 'p' with children, and I am querying for 'p', using

var query = Parent.find({"_id":"562676a04787a98217d1c81e"});
query.select('children');                                   
query.exec(function(err,person){                            
    if(err){                                                    
        return console.error(err);                               
    } else {                                                     
        console.log(person);                                     
    }
});                                                    

I need to access the person object outside the async function. Any idea on how to do this?

Upvotes: 4

Views: 1486

Answers (2)

Reto
Reto

Reputation: 3141

you cannot access it outside of the callback (="the async function" you mentioned). That's how node.js works:

  • your call to the database will take some time - a very long time when you compare it to just execute a simple code statement.
  • Node.js is non-blocking, so it will not wait for the database to return the result, and it wlll continue immediately by executing the code after your query.exec statement.
  • so the code you write after the query.exec statement is run BEFORE the database returns the result, it is therefore impossible to use that result there.

BUT... embrace async programming:

  • just write all the code you need into the "async function"
  • pass a callback into your function, call it from "the async function" and pass it the query result

Upvotes: 0

chridam
chridam

Reputation: 103375

Mongoose's find() method is asynchronous which means you should use a callback that you can wrap the query from the find() method. For example, in your case, you can define a callback as

function getChildrenQuery(parentId, callback){
    Parent.find({"_id": parentId}, "children", function(err, docs){
        if (err) {
          callback(err, null);
        } else {
          callback(null, docs);
        }
    }); 
}

which you can then call like this:

var id = "562676a04787a98217d1c81e";
getChildrenQuery(id, function(err, children) {
    if (err) console.log(err);

    // do something with children
    children.forEach(function(child){
      console.log(child.name);
    });
});

Another approach you may take is that of promises where the exec() method returns a Promise, so you can do the following:

function getChildrenPromise(parentId){
   var promise = Parent.find({_id: parentId}).select("children").exec();
   return promise;
}

Then, when you would like to get the data, you should make it async:

var promise = getChildrenPromise("562676a04787a98217d1c81e");
promise.then(function(children){
    children.forEach(function(child){
        console.log(child.name);
    });
}).error(function(error){
    console.log(error);
});

Upvotes: 5

Related Questions