2016-11-25 1 views
0

J'ai un problème avec le traitement d'un énorme ensemble de données dans NodeJS. J'utilise async parce que je veux appeler un res.send quand tout est terminé.NodeJS async grand ensemble de données callback

Casus:

Dans une collection MongoDB sur ce projet, il est possible d'ajouter des campagnes. Les magasins peuvent se joindre à ces campagnes et ajouter des actions de cette campagne à leur agenda. (comme poster un message Facebook, de la photo sur Instagram) Sur le frontend du site, il y a une page qui montre toutes les campagnes actives. Quand une campagne est ouverte, il doit y avoir une liste avec tous les magasins qui ont rejoint cette campagne. Parce que chaque boutique a un agenda, où est sauvegardé quelles tâches faire, je dois parcourir toutes les boutiques pour voir s'il y a une action avec campaignId ce qui est égal à l'ID de la campagne ce qui est ouvert. Il y a plus de 3500 entrées dans la collection de la boutique, cela peut prendre un certain temps lorsque toutes les boutiques sont traitées, j'ai donc décidé d'utiliser angular pour publier cette requête lorsque la page est chargée.

Problème:

Comme vous pouvez le voir dans le code ci-dessous, je reçois tous les magasins, et la boucle à travers les articles. Ensuite, je parcours les éléments de l'agenda pour voir s'il y a un campaignID correspondant, puis j'ajoute quelques informations dans un tableau que je veux renvoyer. Mais le code s'arrête après 1 magasin. Comment puis-je ajouter tous les magasins dans le tableau et envoyer tous quand tous les magasins sont traités?

Shopmodel:

(pas tous les champs)

var Shop = new Schema({ 
    name:String, 
    email:String, 
    phone: String, 
    agenda:[{ 
     campaignId:Schema.ObjectId, 
     taskId:Schema.ObjectId, 
     campaignName: String, 
     downloaded: Boolean, 
     success: Boolean, 
     startDate:Date, 
     endDate:Date, 
     description:String, 
     kind:String 
    }], 
},{collection:'shop'}); 

code dans le contrôleur:

module.exports.getCampaignShop = function(req,res){ 
    console.log("getCampaignShop"); 
    var campaignId = req.query['campaignId']; 
    console.log("campaignId", campaignId); 
    var result = []; 
    Shop.find().sort({name:1}).exec(function(err, shops){ 
     console.log("shop count", shops.length); 
     async.eachSeries(shops, function(shop, allDone){ 
      async.eachSeries(shop.agenda, function(agenda, shopComplete){ 
       if(agenda.campaignId == campaignId){ 
        var shopResult = { 
         shopId: shop._id, 
         nameSlug: shop.nameSlug, 
         logo: shop.logo, 
         name: shop.name 
        } 
        console.log("shopResult", shopResult); 
        result.push(shopResult); 
        shopComplete(); 
       } 
      }) 
      allDone(); 
     }, function(err){ 
      if (err) throw err; 
      console.log("result length", result.length); 
      res.send(result); 
     }) 

    }) 
} 
+0

Avez-vous essayé de composer une requête qui renvoie uniquement Shop où> 1 élément dans l'agenda a campaingnId égal à ce que vous voulez? MongoDB peut faciliter beaucoup de votre temps – DrakaSAN

Répondre

2

La question est shopComplete rappel s'appelle seulement quand agenda.campaignId == campaignId est vrai. Vous devez l'appeler en dehors du if block.

+0

Ouais! C'était le truc! – NVO

+0

Suggère aussi à NVO d'exécuter une boucle de synchronisation au lieu de 'async.eachSeries (shop.agenda, function (agenda, shopComplete) {' car je ne vois pas pourquoi vous avez besoin d'async là-bas. –