3

I have:

Emotion.find (query, "-_id", opts, function (error, e){
    if (error) return cb (error, 500);
    for (var i=0, len=e.length; i<len; i++){
        e[i] = convert (e[i]);
    }
    cb (null, e);
});

If the function returns 1k documents I have to iterate 1k times.

How can I add a callback that is executed for every document? Something like:

var each = function (e){
    return convert (e);
};

Emotion.find (query, "-_id", opts, each, function (error, e){
    if (error) return cb (error, 500);
    cb (null, e);
});

I basically need to use each() from mongodb: http://mongodb.github.com/node-mongodb-native/api-generated/cursor.html#each


Edit: Perhaps this can be done listening a data event from a stream and pushing the document to an array:

http://mongoosejs.com/docs/api.html#query_Query-stream

Gabriel Llamas
  • 18,244
  • 26
  • 87
  • 112

3 Answers3

5

As I said, with streams:

var emotions = [];

Emotion.find (query, "-_id", opts).stream ()
        .on ("error", function (error){
            cb (error, 500);
        })
        .on ("data", function (doc){
            emotions.push (convert (doc));
        })
        .on ("close", function (){
            cb (null, emotions)
        });

Edit: The above solution is much slower than this:

var emotions = [];

//Get the collection... then:

collection.find (query, opts, function (error, cursor){
    if (error) return cb (error, 500);

    cursor.each (function (error, doc){
        if (error) return cb (error, 500);
        if (!doc) return cb (null, emotions);
        emotions.push (convert (doc));
    });
});
Gabriel Llamas
  • 18,244
  • 26
  • 87
  • 112
  • Yes, but I've noticed that this is much slower than using each() from mongodb – Gabriel Llamas Mar 25 '13 at 15:41
  • 1
    In that case, you might be able to drop down into the native driver from Mongoose, as discussed in [this](http://stackoverflow.com/questions/10519432/how-to-do-raw-mongodb-operations-in-mongoose) question. – shelman Mar 25 '13 at 15:46
  • Just FYI, in the native/faster case you actually get Mongo objects, not Mongoose documents (just like using `lean` with queries). – BorisOkunskiy Aug 31 '13 at 07:28
1

It seems like you might be able to use a query stream to do what you want - however, even with an each() sort of call, you are still essentially iterating over all the returned documents, just with a little syntactic sugar.

shelman
  • 2,689
  • 15
  • 17
1

Simple example code for mongoose/eachAsync, can be usefull for this case:

functionProcess = (callback) => {

  userModel.find().cursor().eachAsync(user => {
    return user.save().exec();        // Need promise
  }).then(callback);     //Final loop

}
Jesus
  • 752
  • 7
  • 5