I have an Express application with Mongoose. I have a model
var AttendeeSchema = new Schema({
name: String,
registered: Boolean
});
var EventSchema = new Schema({
name: String,
description: String,
attendees : [AttendeeSchema],
created: { type: Date, default: Date.now },
updated: { type: Date, default: Date.now }
});
The code for creating an event is:
router.route('/:event_id')
.get(function(req, res) {
Event.findById(req.params.event_id, function(err, event) {
if (err)
res.send(err);
res.json(event);
});
})
.put(function(req, res) {
Event.findById(req.params.event_id, function(err, event) {
if (err)
res.send(err);
event.name = req.body.name;
event.description = req.body.description;
event.attendees: req.body.attendees;
event.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Event updated successfully!' });
});
});
})
The code for updating an event is:
router.route('/:event_id')
.put(function(req, res) {
Event.findById(req.params.event_id, function(err, event) {
if (err)
res.send(err);
event.name = req.body.name;
event.description = req.body.description;
event.attendees: req.body.attendees;
event.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Event updated successfully!' });
});
});
})
The problem is that events are being created successfully however when I try to update an event, it only updates the event name and description, but not changes to the attendees name or registered status. I also noticed that the version is not updated from "__v0" to "__v1"
Anyone some hints as to why I cannot update attendee specific information with the above code?
It looks like you need a = where you have a : ;)
event.attendees: req.body.attendees;
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
So when I use Object.assign, (ex. Object.assign({foo:bar1},{foo:bar2}) on a particular Mongoose Subdocument Schema, the foo:bar2 obj won't overwrite the foo:bar1 obj.
In my app I have an Account Schema with two sub-document schemas, Projects & Properties. It's in the Project sub document schema that I encounter the issue.
Here are my Models:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProjectSchema = new Schema({
_id: String,
name: String,
}, { strict: false })
var PropertySchema = new Schema({
_id: String,
slug: String,
name: String,
type: String,
placeholder: String,
order: Number
}, { strict: false })
var AccountSchema = new Schema({
_id: String,
name: String,
slug: String,
email: String,
properties: [PropertySchema],
projects: [ProjectSchema],
}, { strict: false })
module.exports = mongoose.model('Account', AccountSchema);
Here is a snippet of my Middleware(I think that's what it's called, please correct me if I am wrong). This is where I do the Object.assign to overwrite the particular projects' properties. If it helps I can post all the routes.
router.route('/accounts/:account_id/projects/:project_id')
.get(function(req, res) {
Project.findById(req.params.project_id, function(err, project){
if (err)
res.send(err);
res.json(project);
});
})
.delete(function(req, res){
Account.findById(req.params.account_id, function(err,account){
if (err)
res.send(err);
account.projects.id(req.params.project_id).remove();
account.save(function(err) {
if(err)
res.send(err);
res.json({message: 'Project Deleted'});
});
})
})
.put(function(req, res){
Account.findById(req.params.account_id, function(err,account){
if (err)
res.send(err);
Object.assign(account.projects.id(req.params.project_id), req.body);
account.save(function(err) {
if(err)
res.send(err);
res.json({message: 'Project Updated'});
});
})
});
// ----------------------------------------------------
router.route('/accounts/:account_id/properties/:property_id')
.get(function(req, res) {
Property.findById(req.params.property_id, function(err, property){
if(err)
res.send(err);
res.json(property);
});
})
.delete(function(req, res){
Account.findById(req.params.account_id, function(err, account){
if (err)
res.send(err);
account.properties.id(req.params.property_id).remove();
account.save(function(err){
if(err)
res.send(err);
res.json({ message: 'Successfully Deleted' });
})
})
})
.put(function(req, res){
Account.findById(req.params.account_id, function(err, account) {
if (err)
res.send(err);
Object.assign(account.properties.id(req.params.property_id), req.body);
account.save(function(err) {
if(err)
res.send(err);
res.json({message: 'Property Updated'});
})
})
});
So it's the Put Method that is giving me the issue, I can Get, Post, Delete with no issues, but the Put part for Projects is where I encounter this Object.assign issue. Funny thing is that everything works perfectly for the Property Schema Put Method, and it is basically the exact same as the Project one.
If I console.log some of the values in the Project's Put Method I get the following:
console.log(account.projects.id(req.params.project_id));
//original value logs { _id: '1486609836741', foo: 'bar' }
console.log(req.body);
//updated value logs { foo: 'barred', _id: '1486609836741' }
console.log(Object.assign(account.projects.id(req.params.project_id), req.body));
//logs the original value { _id: '1486609836741', foo: 'bar' }
So when I log the updated and original values they have equal keys, shouldn't the Object.assign work? Is the original Obj more complex then what the console.log displays, and maybe the original and updated don't have equal keys?
I am kinda stumped, any help would be greatly appreciated. Let me know if I need to post more of my code. Thanks.
Object.assign(account.projects.id(req.params.project_id), req.body);
Here, you are trying to assign to an object that is result of MongooseDocumentArray.id method call on account.projects array. Which will affect just a copy of document which is returned by function, and won't affect the original array of subdocuments.
I am new to Mongoose, but I'll suggest you trying to work with account.projects as with MongooseArray:
var project = account.projects.id( req.params.project_id ),
index = account.projects.indexOf( project );
Object.assign( account.projects[ index ], req.body);