sql >> Base de Datos >  >> NoSQL >> MongoDB

Subdocumentos MongoDB mongoose creados dos veces

El bucle forEach en su intento no reconoce la finalización de la devolución de llamada de findById() método asíncrono antes de la siguiente iteración. Debe usar cualquiera de async métodos de biblioteca async.each , async.whilst , o async.until que son equivalentes a un bucle for, y esperarán hasta que se invoque la devolución de llamada de async antes de pasar a la siguiente iteración (en otras palabras, un bucle for que producirá).

Por ejemplo:

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

Para toda la operación, puede usar async.waterfall() método que permite que cada función pase sus resultados a la función siguiente.

La primera función del método crea el nuevo artículo.

La segunda función usa async.each() función de utilidad para iterar sobre la lista de plataformas, realizar una tarea asíncrona para cada ID para actualizar la plataforma usando findByIdAndUpdate() , y cuando hayan terminado, devolver los resultados de la consulta de actualización en una variable de objeto a la siguiente función.

La función final actualizará el artículo recién creado con los ID de plataforma de la canalización anterior.

Algo como el siguiente ejemplo:

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