I have an API in which I am deleting 'course' documents in the following way:
module.exports.deleteCourse = function(req, res){
var courseid = req.params.courseid;
if(courseid){
Course.findByIdAndRemove(courseid, function(err, course){
if(err){
sendJSONResponse(res, 404, err);
return;
}
sendJSONResponse(res, 204, null)
});
} else{
sendJSONResponse(res, 404, {"message":"NoId"});
}
};
This is successful in deleting the course from the database, as is shown when attempting to find it by id.
The issue is that in user documents:
var instructorSchema = new mongoose.Schema({
name: {type: String,
unique: true,
required: true},
password: {type: String,
required: true},
courses: [course.schema]
});
If the document was pushed to the courses array it remains after the deletion method.
So my question. Is there a relatively painless way to keep this document updated after deletes?
Thanks.
Add a class method for course using statics, where you delete both the course and its dependencies.
Assuming you are storing ids in courses array:
var Instructor = require('./instructor');
courseSchema.statics = {
removeOneWithDependencies : function(id, done){
this.findByIdAndRemove(id, function(err, course){
if(err){
return done(err);
}
else{
//Removes the course id from courses array of all instructor docs
Instructor.update({courses: course._id}, { $pullAll: {courses: [course._id] } }, {multi: true}, function(err){ //http://stackoverflow.com/a/27917378/
if(err){
return done(err);
}
else{
return done();
}
})
}
});
}
}
In case you are storing course documents in courses array you need to change the update query to:
Instructor.update({"courses._id": course._id}, { $pull: {courses:{_id: course._id} } }, {multi: true}, function(err){ //http://stackoverflow.com/a/15122017/
Finally use the above method in your API:
module.exports.deleteCourse = function(req, res){
var courseid = req.params.courseid;
if(courseid){
Course.removeOneWithDependencies(courseid, function(err){
if(err){
return sendJSONResponse(res, 500, err);
}
else{
return sendJSONResponse(res, 204, null);
}
});
} else{
sendJSONResponse(res, 404, {"message":"NoId"});
}
};
Related
My User Schema is like this
{
_id:ObjectId("6e9465528a15ba6")
name: 'XYZ',
email: 'abc#gmail.com',
transactions: [
{
_id:ObjectId("5e946557a5128a15ba6"),
date: 2020-04-09T06:00:30.000Z,
type: 'type1',
category: 'category1',
description: 'some desc',
}
]
}
I want to update some fields of transaction with specific id. But not happening.
I tried the solution answered to
Mongoose, update values in array of objects this question.
May be my _id is of type ObjectId and id coming from my request is String?
So how can I solve this problem?
My code is like this but still getiing error user.transactions._id is not function
app.post('/api/update', function (req, res) {
const {
id,
email,
date,
type,
category,
description
} = req.body;
User.findOne({email}, function (err, user) {
if (err) {
console.error(err);
res.status(500)
.json({
error: 'Internal error please try again'
});
} else if (!user) {
res.status(401)
.json({
error: 'Incorrect email or password'
});
} else {
const objectId = mongoose.Types.ObjectId(id);
let transaction = user.transactions._id(objectId);
transaction.date = date;
transaction.type = type;
transaction.category = category;
transaction.description = description;
user.save((err, data) => {
if (err) return res.send(err);
return res.sendStatus(200);
});
}
});
});
fortunately I had to do something similar recently, so I suggest you to have a look at this page from Mongoose docs in the case I miss something, but basically you have to find the document first and then update its array of objects.
I'd try something like this:
User.findOne({ _id: your_user_id }, (err, data) => {
if (err) return console.log(err);
if (data) {
//Mongoose has a special method (id) for subdocuments
var transaction = data.transactions.id(your_transaction_id);
date: new Date(),
type: 'type2',
category: 'category2',
description: 'whatever',
//data.save() saves everything, document and subdocument
data.save((err, data) => {
if (err) return console.log(err);
done(null, data);
});
}
I am a noobie in coding and I am having an issue with how to use properly MongoDB. I have a parent object classroom containing an array of objects - comments. I am trying to update the content of 1 selected comment.
originally I updated the state of the whole "classroom" in the react and passed all the data and $set {req.body} in findByIdAndUpdate.
I want to achieve the same result if I only pass to my axios request classId, commentId and comment data and not whole classroom / all comments
I tried to filter selected comment out of the array of comments and concat updated comment, but that did not work. Clearly, I have any idea what is going on and docs don't make it any easier for me to understand.
my classroom schema:
var ClassroomSchema = new Schema({
title: String,
teacher: String,
info: String,
image_url: String,
comments: [Comment.schema]
});
comment schema:
var CommentSchema = new Schema()
CommentSchema.add({
content: String,
comments: [CommentSchema],
created_at: {
type: Date,
default: Date.now
}
});
original solution:
function update(req, res){
Comment.findById(req.params.comment_id, function(err, comment) {
if(err) res.send(err)
comment.content = req.body.content;
comment.save();
console.log(req.body.comments)
Classroom.findByIdAndUpdate(req.params.classroom_id,
{$set: req.body}, function(err, classroom){
if (err) {
console.log(err);
res.send(err);
} else {
commentToUpdate = req.body.commentData;
res.json(classroom);
}
});
});
}
my current failing atempt:
function update(req, res){
console.log('update => req.body: ', req.body);
console.log('req.params', req.params)
Comment.findById(req.params.comment_id, function(err, comment) {
if(err) res.send(err)
comment.content = req.body.content;
comment.save();
console.log('comment: ', comment);
Classroom.findById(req.params.classroom_id, function(err, classroom) {
console.log('CLASSROOM findByIdAndUpdate classroom: ', classroom)
// console.log('reg.body: ', req.body)
if (err) {
console.warn('Error updating comment', err);
res.send(err);
} else {
// commentToUpdate = req.body.commentData;
old_comments = classroom.comments;
console.log('comments: ', old_comments);
Classroom.findByIdAndUpdate(req.params.classroom_id,
{$set:
{ comments: old_comments.filter(comt._id !== comment._id).concat(comment)}
}, function(err, updatedClassroom) {
if (err) {
console.warn(err);
} else {
res.json(updatedClassroom);
}
});
}
});
});
}
haven't tested, but try this.
function update(req, res) {
Classroom.update(
{ _id: req.params.classroom_id, "comments._id": req.params.comment_id },
{ $set: { "comments.$.content": req.body.content } },
function(err) {
..
}
);
}
I have a mongoose schema having the structure of
const videoProjectsSchema = new Schema({
projectname:String,
projectmeta:String,
username:String,
createdat:{ type: Date, default: Date.now }
});
I need to retrieve a list of projectnames which belongs to a particular user. the array returned should only contain the names of the projects or else a list of projectname. This is my code(which returns all the projects objects)
videoProjects.find({ username: req.query.username }, function(err, proj) {
if (err) {
console.log(err);
}
res.json(proj);
});
You can use fields as second parameter to limit fields returned in object.
videoProjects.find({ username: req.query.username },{projectmeta:0,username:0,createdat:0,_id:0},
function(err, proj) {
if (err) {
console.log(err);
}else
res.json(proj);
});
OR
videoProjects.find({ username: req.query.username },{projectname:1,_id:0},
function(err, proj) {
if (err) {
console.log(err);
}else
res.json(proj);
});
i have a web app that's written in nodejs and mongodb, i have the following two models
var TeacherSchema = new Schema({
school_id:[{type: Schema.Types.ObjectId, ref: 'School'}],
name: String,
subjects: [{type: Schema.Types.ObjectId, ref: 'Subject'}],
});
var SubjectSchema = new Schema({
title : String,
school_id:[{type: Schema.Types.ObjectId, ref: 'School'}]
});
i wrote an api that searches throw the teacher or subjects
router.get("/field-teacher-subject", function (req, res) {
var school_id= req.query.schoolId;
Subject.find(school_id:'school_id,function (err, subjects) {
if (err) {
console.log(err);
res.json({status: "error", message: err.message});
} else {
var sub_array=[];
for(var q in subjects){
sub_array.push(subjects[q]._id);
}
Teacher.find({subjects:{$in :sub_array }},{first_name:true, father_name:true, last_name : true, subjects:true}).populate('subjects')
.exec(function(tech) {
console.log("hello: ");
var subjeto = [];
if(tech){
for(var p in tech){
subjeto.push(tech[p].subjects);
}
}
res.json({status: "success", message: "subjects returned",
items: tech});
}).catch(function(err){
if(err){
res.json({status:"error",
message:"error occurred"+err.message});
return;
}
});
}
}).limit(parseInt(req.query.max));
});
THIS RETURNS null when i search for a name,
what is the best way to solve this
Hard to know what you are asking but your code has few errors. Let's clean up your code, shall we?
router.get("/field-teacher-subject", function (req, res) {
// get subjects
Subject
.find({ school_id: req.query.schoolId }) // 1st argument is an object
.limit(parseInt(req.query.max)) // should go before
.exec(function (err, subjects) { // use .exec()
if (err) {
console.log(err);
return res.json({ status: "error", message: err.message });
}
// get subject IDs
var sub_array = subjects.map(function (subject) { return subject._id; });
// get teachers assigned to subjects
Teacher
.find({ subjects: { $in: sub_array }})
.select('first_name father_name last_name subjects')
.populate('subjects')
.exec(function(err, teachers) { // 1st argument is an error
if (err) {
console.log(err);
return res.json({status: "error", message: err.message });
}
var subjeto = teachers.map(function (teacher) { return teacher.subjects; });
res.json({status: "success", message: "subjects returned", items: teachers });
});
});
});
Useful links:
See 3rd example in doc on how to use .limit() and .exec().
.map()
You tried to use .exec() like .then() and .catch() in your second query
I'm new to MongoDb and I met this problem days ago and I can't resolve it. Basically, my user is allowed to create new Post with a bunch of Images. When I create the Post, then I create also the Images but when I check on mongo shell the entries in the array of the Post, one image can be present two or three times. (All the images are saved with an url)
These are my Models:
var postSchema = new mongoose.Schema({
Name: String,
Background: String,
Description: String,
posted: {type:Date,default: Date.now() },
images: [{type: mongoose.Schema.Types.ObjectId, ref: "image"}]
});
var imageSchema = new mongoose.Schema({
src: String,
caption: String
});
(These Schema are in separeted files and then exported as model)
This is my code for saving Post:
app.post("/post",isLoggedIn,function(req,res){
var post= {Name: req.body.name,
Background: req.body.backg,
Description: req.body.desc};
Posts.create(post, function(err, newPost){
if(err){
console.log(err);
} else {
var allImages = req.body.img;
allImages.forEach(function(singleImg){
Images.create(singleImg, function(err, newImg){
if(err){
console.log(err);
} else {
newPost.images.push(newImg);
newPost.save(function(err){
if(err){
return res.send(err);
}
});
}
});
});
}
});
return res.redirect("/posts");
});
Edit
This is my code with $addToSet
app.post("/post",isLoggedIn,function(req,res){
var post= {Name: req.body.name,
Background: req.body.backg,
Description: req.body.desc};
Posts.create(post, function(err, newPost){
if(err){
console.log(err);
} else {
Posts.findByIdAndUpdate(newPost._id, {$addToSet:{images: {$each: req.body.img}}}, function(err, updatedPost){
return res.redirect("/posts");
});
}
});
});
It gives me CastError Cast to ObjectId failed
Don't forget hanlde errors
Edit your code: (With Mongoose + nodejs - I suggest use indexOf, It runs very well with me, My DB have about 10M records)
From
Posts.create(post, function(err, newPost){
if(err){
console.log(err);
} else {
var allImages = req.body.img;
allImages.forEach(function(singleImg){
Images.create(singleImg, function(err, newImg){
if(err){
console.log(err);
} else {
newPost.images.push(newImg);
newPost.save(function(err){
if(err){
return res.send(err);
}
});
}
});
});
}
});
to
Posts.create(post, function(err, newPost){
if(err){
console.log(err);
} else {
var allImages = req.body.img;
allImages.forEach(function(singleImg){
Images.create(singleImg, function(err, newImg){
if(err){
console.log(err);
} else {
// Check exist
if (newPost.images.indexOf(newImg._id) == -1) {
newPost.images.push(newImg._id);
newPost.save(function(err){
if(err) {
return res.send(err);
}
});
} else {
console.log(newImg);
// do something
}
}
});
});
}
});
OR
Use $addToSet if you use MongoDb or Mongoose
Hope it will help you.
Thank you