2012-08-11 12 views
7

¿Cómo administro el almacenamiento por lotes en Mongoose? Vi que no puede ser posible sin embargo:Mongoose JS promete? O cómo administrar el almacenamiento por lotes

Theres alguna mención sobre el uso de alguna biblioteca de control de flujo como q, sino también noto que hay en promises mangosta, lo puedo usar? ¿Puedo hacer como en jQuery Diferido/promesas

$.when(obj1.save(), obj2.save(), obj3.save()).then -> 
    # do something? 

Respuesta

3

Pruebe la función parallel del módulo async.

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); 
}); 
2

Para guardar múltiples documentos mangosta en paralelo, se puede hacer algo tan simple como este (suponiendo que tiene una matriz llamada docs de documentos para guardar):

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

con una elegante sobre cómo utilizar async parallel sería:

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

Desde la convención es la misma en Mangosta como en asíncrono (err, devolución de llamada) que no es necesario envolverlos en sus propias devoluciones de llamada, simplemente agregue sus llamadas guardadas en una matriz y obtendrá una devolución de llamada cuando todo haya terminado.

+1

O a batch-save una matriz: async.map (objetos, función (objeto, siguiente) {object.save (next)}, callback); –

+0

Gracias. Creo que el enfoque del mapa es mejor. Pero ambos están bien. –

9

Sí, puede hacerlo con promesas. código si estuviera usando la biblioteca Q promesa, podría volver a escribir @ de matz3 como:

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); 
    }); 

Empezamos todas las operaciones de uno a la vez en el circuito, pero no esperan a que cualquiera de ellos para completa, por lo que se ejecutan en paralelo. Agregamos una promesa (que actúa como un marcador de posición para el resultado) a una matriz. Luego esperamos a que se cumplan todas las promesas en la serie de promesas.

más bien Promises/A+ bibliotecas compatibles tienen algún equivalente a Q.all

+0

Nuevo en esto, podría ser incorrecto. Pero su save() allí al construir la matriz, ¿no debería excluir el() para que no se evalúe al construir la matriz? – Slappy

+1

No, estoy comenzando las operaciones en la matriz, así que necesito incluir '()'. Eso luego devuelve un objeto 'promesa' que puse en la matriz. Es paralelo porque solo recibo una promesa, no el resultado final real. Al final, luego espero a que esas promesas se resuelvan. – ForbesLindesay

+1

Si tuviera que omitir el '()' obtendría una serie de funciones, y no hay una cosa universalmente reconocida que ver con una serie de funciones. Por ejemplo, podría querer que se ejecuten uno a la vez en lugar de hacerlo en paralelo, o podrían recibir una devolución de llamada en lugar de devolver una promesa. Sin embargo, hay una manera reconocida de esperar que se cumplan una serie de promesas. – ForbesLindesay

-1

¿Qué pasa con async.queue.
Un ejemplo sencillo:

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); 
} 

Si necesita una devolución de llamada después de vaciarse la cola:

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(); 
} 
+0

¿Por qué un voto a favor? – mathieug

-1

@ForbesLindesay Por qué cargar una biblioteca externa cuando se puede utilizar la aplicación mangosta de las promesas y crear su propio Todas ?

Cree un módulo que mejore la promesa de la mangosta con todos.

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; 

Entonces utilizarlo con mangosta:

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); 
    }); 
+0

Bueno, parece más simple usar mpromise que se usa dentro de mangosta: 'var Promise = require ('mpromise');' luego use 'Promise.all (...)'. –

4

mangosta ahora le permite elegir que prometen aplicación.

Aquí estoy usando el nodo.sistema por defecto js Promise (ES6) al horno en 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(); 
}); 

nodo --version v4.1.1

[email protected]

1

Desde mongoose ahora es compatible con las promesas puede usar Promise.all().then(), por lo que regresará cuando se hayan resuelto todas las promesas.

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

De hecho, si siempre estás llamando al método save() puede utilizar el Array.map() aquí:

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

aaand también utilizan es6 sintaxis para desestructurar la matriz resultante:

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