Reputation: 27
req.body.courses has multiples id's of courses that I want to add to a specific categorie, the problem is that when my code runs it save a course more that one time, sometimes four or five times, depending on the number of loops it does.
The function:
router.post('/categories/:cat_id/', function (req, res) {
Categorie.findById(req.params.cat_id, function(err, categorie){
if(err){
console.log(err);
} else {
var courses = req.body.courses;
courses.forEach(function (course){
Course.findOne({ _id: course }, function(err, foundCourse) {
if(err){
console.log(err);
} else {
categorie.courses.push(foundCourse._id);
categorie.save();
}
});
});
}
});
return res.redirect('/dash');
});
The CategorieSchema:
var categorieSchema = mongoose.Schema({
name: String,
courses: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Course"
}
]
});
Here is an example of trying to add 4 courses to the categorie:
{ "_id" : ObjectId("5a871964a6b4820ecf7abaa7"), "courses" : [ ObjectId("5a870a7374486e0b0d69f710"), ObjectId("5a870a7a74486e0b0d69f711"), ObjectId("5a870a6974486e0b0d69f70f"),
ObjectId("5a870a7374486e0b0d69f710"), ObjectId("5a870a7a74486e0b0d69f711"), ObjectId("5a870a6974486e0b0d69f70f"),
ObjectId("5a870a7374486e0b0d69f710"), ObjectId("5a870a7a74486e0b0d69f711"), ObjectId("5a870a6974486e0b0d69f70f") ], "name" : "test2", "__v" : 3 }
Upvotes: 0
Views: 60
Reputation: 103425
An alternative would involve a first query returning the courses using $in
operator with Course.find()
and then update the courses
array in the Categorie model with Categorie.findByIdAndUpdate()
:
router.post('/categories/:cat_id/', function (req, res) {
Course.find({ '_id': { '$in': req.body.courses }}).exec((err, courses) => {
Categorie.findByIdAndUpdate(
req.params.cat_id,
{ '$addToSet': { 'courses': courses } },
{ 'new': true },
(err, categorie) => {
if (err){
console.log(err);
} else {
return res.redirect('/dash');
}
}
});
});
});
Upvotes: 0
Reputation: 10111
Node.js Is async, It does not wait for the loop to execute completely and each time you are adding _id in existing array because of that adds 2-3 times.
Try this once I have not tested this.
const findOne = (course) => {
return new Promise((resolve, reject) => {
Course.findOne({
_id: course
}, (err, foundCourse) => {
if (err)
return reject(err);
return resolve(foundCourse._id);
});
});
}
router.post('/categories/:cat_id/', function (req, res) {
Categorie.findById(req.params.cat_id, function (err, categorie) {
if (err) {
console.log(err);
res.status(400).json(err);
} else {
var courses = req.body.courses;
Promise.all(courses.map((course) => {
return findOne(course);
})).then((data) => {
// check if course id already there skip
data = data.filter((course) => {
return !categorie.courses.includes(course);
});
categorie.courses = categorie.courses.concat(data);
categorie.save();
return res.redirect('/dash');
}).catch((err) => {
console.log(err);
res.status(400).json(err);
});
}
});
});
Upvotes: 1