MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Sous-documents MongoDB mongoose créés deux fois

La boucle forEach de votre tentative ne reconnaît pas la fin du rappel de findById() méthode async avant la prochaine itération. Vous devez utiliser l'un des async méthodes de bibliothèque async.each , async.whilst , ou async.until qui sont équivalentes à une boucle for, et attendront que le rappel d'async soit invoqué avant de passer à l'itération suivante (en d'autres termes, une boucle for qui donnera).

Par exemple :

var platform_docs = [];
async.each(platforms, function(id, callback) {
    Platform.findById(id, function(err, platform) {
        if (platform) 
            platform_docs.push(platform);
        callback(err);
    });
}, function(err) {
   // code to run on completion or err
   console.log(platform_docs);
});

Pour toute l'opération, vous pouvez utiliser le async.waterfall() méthode qui permet à chaque fonction de transmettre ses résultats à la fonction suivante.

La première fonction de la méthode crée le nouvel article.

La deuxième fonction utilise le async.each() fonction utilitaire pour itérer sur la liste des plates-formes, effectuer une tâche asynchrone pour chaque identifiant pour mettre à jour la plate-forme en utilisant findByIdAndUpdate() , et lorsqu'ils ont tous terminé, ils renvoient les résultats de la requête de mise à jour dans une variable objet à la fonction suivante.

La fonction finale mettra à jour l'article nouvellement créé avec les identifiants de plate-forme du pipeline précédent.

Quelque chose comme l'exemple suivant :

var newArticle = {},
    platforms            = req.body.platforms,
    date                 = req.body.date,
    split                = date.split("/");

newArticle.title         = req.body.title;
newArticle.description   = req.body.description;
newArticle.date          = split[2]+'/'+split[0]+'/'+split[2];
newArticle.link          = req.body.link;
newArticle.body          = req.body.body;
console.log(platforms);

async.waterfall([

    // Create the article
    function(callback) {
        var article = new Article(newArticle);
        article.save(function(err, article){
            if (err) return callback(err);                  
            callback(null, article);
        });
    },

    // Query and update the platforms 
    function(articleData, callback) {
        var platform_ids = [];
        async.each(platforms, function(id, callback) {
            Platform.findByIdAndUpdate(id, 
                { "$push": { "articles": articleData._id } },
                { "new": true },
                function(err, platform) {
                    if (platform) 
                        platform_ids.push(platform._id);
                    callback(err);
                }
            );
        }, function(err) {
            // code to run on completion or err
            if (err) return callback(err);                  
            console.log(platform_ids);
            callback(null, {
                "article": articleData,
                "platform_ids": platform_ids
            });
        });         
    },

    // Update the article
    function(obj, callback) {
        var article = obj.article;
        obj.platform_ids.forEach(function(id){ article.platforms.push(id); });
        article.save(function(err, article){
            if (err) return callback(err);                  
            callback(null, article);
        });
    }   

], function(err, result) { 
/*
    This function gets called after the above tasks 
    have called their "task callbacks"
*/
    if (err) return next(err);
    console.log(result);
    res.redirect('articles/' + result._id);
});