Mongoose JS promises? Or how to manage batch saving

How do I manage batch saving in Mongoose? I saw that this is not yet possible:

In some cases, the use of a flow control library is mentioned, for example q , but I also notice there promises in the mongoose, can it be used? Can I do this in jQuery Deferred / Promises

 $.when(obj1.save(), obj2.save(), obj3.save()).then -> # do something? 
+7
source share
8 answers

Try the parallel async function.

 var functions = []; for (var i=0; i < docs.length; i++) { functions.push((function(doc) { return function(callback) { doc.save(callback); }; })(docs[i])); } async.parallel(functions, function(err, results) { console.log(err); console.log(results); }); 
+3
source

Yes, you can do this with promises. If you used the Q promise library, you can rewrite @ matz3 code, for example:

 var tasks = []; for (var i=0; i < docs.length; i++) { tasks.push(docs[i].save()); } Q.all(tasks) .then(function(results) { console.log(results); }, function (err) { console.log(err); }); 

We start all operations one at a time in the cycle, but we do not wait for the completion of their completion, so they work in parallel. We add a promise to the array (which acts as a placeholder for the result). Then we expect all promises in the promises array to complete.

Most good Promises / A + compatible libraries have some Q.all equivalent

+9
source

mongoose now allows you to choose a Promise implementation.

Here I use node.js Promise default system (ES6), baked in nodejs

 var mongoose = require('mongoose'); mongoose.Promise = global.Promise; // use system implementation Promise.all(obj1.save(), obj2.save(), obj3.save()) .then(function(resultSaves) { console.log('parallel promise save result :'); console.log(resultSaves); mongoose.disconnect(); }).catch(function(err) { console.log('ERROR on promise save :'); console.log(err); mongoose.disconnect(); }); 

node - version v4.1.1

mongoose@4.1.8

+4
source

To save multiple concurrent mongoose documents, you can do something simple (suppose you have an array called docs to save documents):

 var count = docs.length; docs.forEach(function(doc) { doc.save(function(err, result) { if (--count === 0) { // All done; call containing function callback return callback(); } }); }); 
+2
source

A refined example of using asynchronous parallel :

  async.parallel([obj1.save, obj2.save, obj3.save], callback); 

Since the convention in Mongoose is the same as in async (err, callback), you do not need to wrap them in your own callbacks, just add your save calls to the array and you will get a callback when everything is complete.

+1
source

Since mongoose now supports promises, you can use Promise.all().then() , so it will be returned when all promises are resolved.

 Promise.all([ obj1.save(), obj2.save(), obj3.save() ]) .then(console.log) .catch(console.error) 

In fact, if you always call save() , you can use Array.map() here:

 Promise.all([ obj1, obj2, obj3 ].map( obj => obj.save() ) 

Aaand also use es6 syntax to destroy the resulting array:

 Promise.all([ obj1, obj2, obj3 ].map( obj => obj.save() ) .then( ([ savedObj1, savedObj2, savedObj3 ]) => { // do something with your saved objects... }) 
+1
source

How about async.queue .
A simple example:

 var queue = async.queue(function(obj, callback) { return obj.save(callback); }); for (var i in objs) { var obj = objs[i]; // Some changes on object obj queue.push(obj); } 

If you need feedback after the queue is released:

 var emptyQueue = true; var queue = async.queue(function(obj, callback) { return obj.save(callback); }); queue.drain = function() { // Every callbacks are finished // bigCallback(); }; for (var i in objs) { var obj = objs[i]; // Some changes on object obj queue.push(obj); emptyQueue = false; } if (emptyQueue) { // Call manually queue drain in case of the queue is empty // and we need to call bigCallback() for example return queue.drain(); } 
-one
source

@ForbesLindesay Why download an external library when you can use the mongoose implementation of promises and create your own All?

Create a module that will enhance the mongoose promise with everyone.

 var Promise = require("mongoose").Promise; Promise.all = function(promises) { var mainPromise = new Promise(); if (promises.lenght == 0) { mainPromise.resolve(null, promises); } var pending = 0; promises.forEach(function(p, i) { pending++; p.then(function(val) { promises[i] = val; if (--pending === 0) { mainPromise.resolve(null, promises); } }, function(err) { mainPromise.reject(err); }); }); return mainPromise; } module.exports = Promise; 

Then use it with mongoose:

 require('./promise') ... var tasks = []; for (var i=0; i < docs.length; i++) { tasks.push(docs[i].save()); } mongoose.Promise.all(tasks) .then(function(results) { console.log(results); }, function (err) { console.log(err); }); 
-one
source

All Articles