Reputation: 81
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
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"); })
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