saver
saver

Reputation: 81

Mongoose aggregate cursor promise

I am trying to aggregate a large data set so I am using a cursor along with aggregate. However, I cannot find documentation on how to implement this without using an additional deferred. I feel there has to be a way to combine aggregate().cursor().each() with a promise that is resolved after aggregation is finished. Does anyone know how to do this?

This code works and is based on http://mongoosejs.com/docs/api.html#aggregate_Aggregate-cursor I am trying to find a way to do this without the additional promise.

aggregation = MyModel.aggregate().group({
  _id: '$name'
});

deferred = Q.defer();

aggregation.cursor({
  batchSize: 1000
}).exec().each(function(err, doc) {
  if (err) {
    return deferred.reject(err);
  }
  if (!doc) {
    return deferred.resolve(); // done
  }
  // do stuff with doc
});
return deferred.promise;

Upvotes: 2

Views: 10943

Answers (1)

Dylan Knight
Dylan Knight

Reputation: 151

I found this SO looking for general help on using the aggregation cursor with promises. After a lot of trial and error and if anyone else stumbles on this, I found that the cursor object has a next() method that returns a promise, like other cursors. For some reason, I couldn't get a reference to it without the async flag, though. So if you're using bluebird:

let bluebird = require("bluebird");
let aggregation = MyModel.aggregate().group({
  _id: '$name'
});

aggregation.cursor({
  batchSize: 1000,
  async: true
}).exec().then(cursor => {
  return bluebird.coroutine(function* () {
    let doc;
    while ((doc = yield cursor.next())) {
      console.log(doc._id)
    }
  })()
}).then(() => { console.log("done with cursor"); })

Update for Mongoose 5

The exec() call no longer returns a promise, just the cursor itself, and the async: true property is no longer necessary.

let aggregation = MyModel.aggregate().group({
  _id: '$name'
});

(async function () {
  let doc, cursor;
  cursor = aggregation.cursor({batchSize: 1000}).exec();

  while ((doc = await cursor.next())) {
    console.log(doc._id)
  }
})()
.then(() => console.log("done with cursor"); )

Upvotes: 5

Related Questions