103 votes

Comment puis-je enregistrer plusieurs documents simultanément dans Mongoose/Node.js?

Actuellement, j'utilise la méthode save pour ajouter un seul document. Supposons que j'ai un tableau de documents que je souhaite stocker en tant qu'objets individuels. Existe-t-il un moyen de les ajouter tous avec un seul appel de fonction et ensuite d'obtenir un seul rappel lorsque c'est fait? Je pourrais ajouter tous les documents individuellement, mais gérer les rappels pour savoir quand tout est terminé serait problématique.

0 votes

Vous devez contrôler le flux de code en utilisant une sorte de bibliothèque asynchrone comme async. (il y a une fonction parallèle et une fois terminée, le rappel est appelé)

0 votes

9voto

Munim Points 2358

Je sais que c'est une vieille question, mais cela m'inquiète qu'il n'y ait pas de réponses correctes ici. La plupart des réponses parlent simplement d'itérer à travers tous les documents et de les enregistrer individuellement, ce qui est une MAUVAISE idée si vous avez plus que quelques documents, et le processus est répété même pour une demande sur beaucoup.

MongoDB a spécifiquement un appel batchInsert() pour insérer plusieurs documents, et cela devrait être utilisé avec le pilote natif de mongodb. Mongoose est construit sur ce pilote, et il n'a pas de support pour les insertions par lots. Cela a probablement du sens car il est censé être un outil de modélisation de document objet pour MongoDB.

Solution: Mongoose est livré avec le pilote natif de MongoDB. Vous pouvez utiliser ce pilote en le nécessitant require('mongoose/node_modules/mongodb') (pas trop sûr à ce sujet, mais vous pouvez toujours réinstaller le mongodb npm si cela ne fonctionne pas, mais je pense que ça devrait) et ensuite faire un batchInsert correct

2 votes

Faux, la réponse de Pascal passe complètement à côté du sujet. Les personnes qui ont besoin d'insertion en masse ont tendance à en avoir besoin parce qu'elles veulent insérer 10 000 000 d'éléments en une seule fois. Sans insertion en masse, une opération qui devrait prendre quelques secondes peut prendre des heures. Model.create est un échec épique, car il prétend être une insertion en masse mais sous le capot, c'est juste une boucle for.

0 votes

Mongoose a sérieusement besoin d'une refonte. De plus, leur documentation laisse BEAUCOUP à désirer.

0 votes

Je pense que la question de @Yashua adresse ce sujet en utilisant le pilote JavaScript mongodb sous-jacent.

9voto

inxilpro Points 3475

Les nouvelles versions de MongoDB prennent en charge les opérations groupées :

var col = db.collection('people');
var batch = col.initializeUnorderedBulkOp();

batch.insert({name: "John"});
batch.insert({name: "Jane"});
batch.insert({name: "Jason"});
batch.insert({name: "Joanne"});

batch.execute(function(err, result) {
    if (err) console.error(err);
    console.log('Inséré ' + result.nInserted + ' ligne(s).');
}

9voto

Praveen Points 577

Utilisez la fonction insertMany pour insérer de nombreux documents. Cela envoie une seule opération au serveur et Mongoose valide tous les documents avant de les envoyer au serveur mongo. Par défaut, Mongoose insère les éléments dans l'ordre où ils existent dans le tableau. Si vous n'avez pas besoin de maintenir un ordre, alors définissez ordered:false.

Important - Gestion des erreurs :

Quand ordered:true la validation et la gestion des erreurs se font en groupe, ce qui signifie que si une échoue, tout échouera.

Quand ordered:false la validation et la gestion des erreurs se font individuellement et l'opération continue. Les erreurs seront renvoyées dans un tableau d'erreurs.

6voto

ämbi Points 3692

Voici une autre façon de le faire sans utiliser de bibliothèques supplémentaires (aucune vérification d'erreur incluse)

function saveAll( callback ){
  var count = 0;
  docs.forEach(function(doc){
      doc.save(function(err){
          count++;
          if( count == docs.length ){
             callback();
          }
      });
  });
}

4voto

Kristian Benoit Points 612

Vous pouvez utiliser la promesse retournée par mongoose save, Promise dans mongoose n'a pas tout, mais vous pouvez ajouter la fonctionnalité avec ce module.

Créez un module qui améliore la promesse mongoose avec all.

var Promise = require("mongoose").Promise;

Promise.all = function(promises) {
  var mainPromise = new Promise();
  if (promises.length == 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;

Ensuite, utilisez-le avec mongoose :

var Promise = require('./promise')

...

var tasks = [];

for (var i=0; i < docs.length; i++) {
  tasks.push(docs[i].save());
}

Promise.all(tasks)
  .then(function(results) {
    console.log(results);
  }, function (err) {
    console.log(err);
  })

0 votes

Uncaught TypeError: Promise resolver undefined is not a function in Promise.js

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X