2016-04-01 3 views
2

Comment itérer un tableau d'objets à mettre à jour des documents avec MongoDB et conserver les documents modifiés pour revenir dans la réponsemise à jour plusieurs documents avec MongoDB

Notez les commentaires dans le code

.put(function (req, res) { 

    var data = req.body.data; 
    var documents = []; 
    for (var item in data) { 

     var id = data[item]._id; 
     var document = data[item]; 

     Item.update({ _id: id }, document, { overwrite: true }, function (err, item) { 
      if (err) { 
      res.send({'error':'Error'}); 
      } 
      Item.findById(id, function (err, document) { 
      if (err) { 
       res.send({}); 
      } 
      documents.push(document); // documents are pushed 
      }); 

     });   
    } 
    documents ; // value is [] 
    res.json({ 
     items: documents 
    });   
}) 

Répondre

2

Utilisez Promise.all() et .findByIdAndUpdate() à la place. Tant que votre soutient les contructs enviroment de ES6, ou vous importez quelque chose qui fournit le Promise.all():

Promise.all(
    req.body.data.map(function(doc) { 
     var id = doc._id; 
     delete doc._id; 
     return Item.findByIdAndUpdate(id,doc,{ "new": true }); 
    }) 
).then(function(documents) { 
    res.json({ "items": documents }) 
}); 

Pas besoin de bibliothèques externes.

+0

cela semble une meilleure solution, mais "return Item.findByIdAnUpdate (id, doc, {" new ": true});" lance une exception: "Erreur de type n'est pas une fonction" à la place je la change pour "return {test:" test "}" et fonctionne bien. –

+0

@Jordi "typo" '.findByIdAndUpdate()' et non '.findByIdAnUpdate()' qui manquait le '" d "' dans '" And "'. Les points entiers "était" et "est" que vous n'avez pas besoin d'importations supplémentaires, et que deuxièmement, le '.findByIdAndUpdate()' est mieux que séparer les opérations de '.update()' et '.findById()'. Non seulement deux voyages au serveur au lieu d'un, mais n'est pas "vraiment" le document dans l'état directement après la modification est faite. D'autres opérations auraient pu éventuellement être modifiées dans les deux. Mais ce n'est pas le cas pour l'une des varties '.find ** AndUpdate()'. –

+0

Oui, était un je "faute de frappe", désolé et merci @BlakesSeven. –

1

Puisque update est asynchrone, votre documents est vide et revient immédiatement. Créez des promesses pour chacune des mises à jour. Créez également un tableau de promesses externe. Poussez ces promesses à ce tableau, et envoyez la réponse lorsque tout est fait. J'utilise le Q library

.put(function (req, res) { 

    var data = req.body.data; 
    var documents = []; 
    var promises = [] 
    for (var item in data) { 

     var id = data[item]._id; 
     var document = data[item]; 
     var itemDefer = Q.defer(); 

     Item.update({ _id: id }, document, { overwrite: true }, function (err, item) { 
      if (err) { 
      res.send({'error':'Error'}); 
      } 
      Item.findById(id, function (err, document) { 
      if (err) { 
       itemDefer.reject(err); 
      } 
      itemDefer.resolve(document); 
      }); 
     }); 
     promises.push(itemDefer.promise);  
    } 
    Q.all(promises).then(function(documents) { 
     res.json({items: documents});  
    }, then(function(err) { 
     res.send({}) 
    })) 

})