user541020
user541020

Reputation: 267

Callbacks with node.js/MongoDB/Mongoose

I'm trying to learn the Mongoose ORM for MongoDB and node.js. I want to query documents in my database, perform an action on each one, and then perform another action after all of the previous actions are complete. In other words, I want to do something like this, assuming I have a model called 'User:'

var userArray = [];
User.find({})
.each(function(user) {
    user.age += 1;
    userArray.push(user);
})
.then(function() {
    //do something with userArray
    //happens after all the users' ages are modified
});

What is the correct syntax for doing something like this in Mongoose?

Upvotes: 1

Views: 2473

Answers (2)

Kostia
Kostia

Reputation: 6304

There are modules for this. Try using async (https://github.com/caolan/async). It allows for running commands and then executing a callback once all are done.

async.parallel([
    function(){ ... },
    function(){ ... }
], callback);

Upvotes: 1

Coleman S
Coleman S

Reputation: 498

If you only need to perform synchronous actions for each document, the solution is fairly simple. (console.warn() is synchronous, so you can use it to verify that all user objects are processed first.)

User.find({}).execFind(function(err, users) {
     users.forEach(function(user) {
          user.age += 1;
          userArray.push(user);
          console.warn('x');
     });
     // then...
     console.warn('y');
});

If you need to perform some sort of asynchronous action (perhaps another db query), the solution becomes more complex. I encountered this issue recently and briefly debated using a module such as Step or rolling my own barebones solution. Step provided more functionality than I needed, so I decided that the added overhead was not worth it. Here is my solution:

    var count = 0;
A.find({ b : c }, ['d', 'e', 'f']).sort(['d'], -1).execFind(function(err, g) {
    g.forEach(function(h) {
        h.a = [];
        B.find({ b : c }, ['d', 'e', 'f', 'g']).execFind(function(err, z) {
            g.v = z;
            if (++count == g.length)
                res.render('z.jade', { locals : { title : 'Q', j : g } });
        });
    });
});

Please pardon the obfuscation (I yanked that right from the source of a project that is under-wraps). Essentially, you wait until the final async operation to complete.

Upvotes: 2

Related Questions