MongoDB mongoose subdocuments created twice

I use a simple form that can be used to register an article on a website.

The appearance is as follows:

// Post new article
app.post("/articles", function(req, res){
   var newArticle = {};
   newArticle.title         = req.body.title;
   newArticle.description   = req.body.description;
   var date                 = req.body.date;
   var split                = date.split("/");
   newArticle.date          = split[1]+'/'+split[0]+'/'+split[2];
   newArticle.link          = req.body.link;
   newArticle.body          = req.body.body;
   var platforms = req.body.platforms;
   console.log(platforms);
  Article.create(newArticle, function(err, createdArticle){
      if(err){
          console.log(err.message);
      } else {
           var counter=0;
            platforms.forEach(function(platform){

               var platformed=mongoose.mongo.ObjectID(platform);
               Platform.findById(platformed, function(err, foundPlatform){
                  if(err){
                      console.log(err);
                  } else {
                      counter++;
                        foundPlatform.articles.push(createdArticle);
                        foundPlatform.save();
                        createdArticle.platforms.push(foundPlatform);
                        createdArticle.save();
                        if(counter==platforms.length){
                            res.redirect('articles/' + createdArticle._id);
                        }
                    }
                });
            });

      }


  });

});

The platform field is passed to the end of the array as an array of strings, one line is one object identifier. When there is only one line on the platforms, that is, one platform to which you need to connect, everything works fine. When platforms contain multiple lines. The created article has duplicates of each platform. Or sometimes only duplicates of some platforms

Any ideas?

UPDATE 1: Article outline: var mongoose = require ("mongoose");

var articleSchema = new mongoose.Schema({
    title        :   String,
    description  :   String, 
    link         :   String,
    date         :   String,
    body         :   String,
    platforms    :   [
      {
         type: mongoose.Schema.Types.ObjectId,
         ref: "Platform"
      }
   ] 
})

module.exports = mongoose.model("Article", articleSchema);

Platform platform:

var mongoose = require("mongoose");

var platformSchema = new mongoose.Schema({
    name        :   String,
    category            :   String,
    contacts          :   [
      {
         type: mongoose.Schema.Types.ObjectId,
         ref: "Contact"
      }
   ],
   website              :   String,
   country              :   String,
   contactInformation   :   String,
   businessModelNotes   :   String,
   source               :   String,
   generalNotes         :   String,
   projects             :   [
      {
         type: mongoose.Schema.Types.ObjectId,
         ref: "Project"
      }
   ],
   articles             :   [
      {
         type: mongoose.Schema.Types.ObjectId,
         ref: "Article"
      }
   ],
   privacy              :   String,
   comments             :   [
      {
         type: mongoose.Schema.Types.ObjectId,
         ref: "Comment"
      }
   ]


});



module.exports = mongoose.model("Platform", platformSchema);
+1
2

forEach async findById() . async async.each, async.whilst async.until, for, , , ( , for, ).

:

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

async.waterfall(), .

.

async.each() , findByIdAndUpdate(), , .

.

- :

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

if(counter==platforms.length){
     createdArticle.save(function(err, savedObject){
        if(err || !savedObject) console.log(err || "not saved");
        else {
          res.redirect('articles/' + savedObject._id.toString());
        }
     });
}

============= EDIT

, article.save , . , save() , .

, :

} else {
  var counter=0;
  // map plateform array id with ObjectID
  var idarray = platforms.map(function(e){return mongoose.mongo.ObjectID(e);});

  // update all plateform with article id
  Platform.update({_id:{$in: idarray}}, {$push:{articles: createdArticle}}, {multi:true, upsert:false}, function(err, raw){
    if(err)
    {
       // error case
       return res.status(403).json({});
    }
    // retrieve plateform
    Platform.find({_id:{$in: idarray}}, function(err, results){
      if(err || !results)
      {
          // error case 
          return res.status(403).json({});
      }
      Article.update({_id: createdArticle._id.toString()}, {$push:{platforms:{$each: results}}}, {multi:false, upsert:false}, function(err, saved){
          if(err || !saved)
          {
             // error
              return res.status(403).json({});
          }
          res.redirect('articles/' + savedObject._id.toString());
     });
   });
 });

, id?

+1

Source: https://habr.com/ru/post/1014848/


All Articles