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) {
..
}
);
}
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);
});
}
Been banging my head in the wall on this, so any help would be greatly appreciated. With MongooseJS, I'm doing a Model.find and then looping through those results and doing a findAndUpdate.
(basically, get list of URLS from MongooseJS, "ping" each URL to get a status, then update the DB with the status).
Schema
var serverSchema = new Schema({
github_id: { type: String, required: true },
url: { type: String, required: true },
check_interval: Number,
last_check: {
response_code: Number,
message: String,
time: Date
},
created_at: Date,
updated_at: Date
})
Here's a code snippet:
// Doesn't work
Server.find(function (err, items) {
if (err) return console.log(err)
items.forEach(function (item) {
var query = {url: item.url}
Server.findOneAndUpdate(query, {updated_at: Date.now()}, function (err, doc) {
if (err) return console.log(err)
console.log(doc)
})
})
})
// Works!
var query = {url: 'https://google.com'}
Server.findOneAndUpdate(query, {updated_at: Date.now()}, function (err, doc) {
if (err) return console.log(err)
console.log(doc)
})
With debugging on, I can see that the .find() is getting the data I want. However, it seems that he findOneAndUpdate within the .find() never runs (item.url is set correctly) and I don't get any errors, it just doesn't run.
Any help would be GREATLY appreciated.
You can achieve that without find and then update you can do this in only one update operation
Server.update({}, { $set: { updated_at: Date.now() } }, function(err, doc) {
if (err) return console.log(err) {
console.log(doc)
}
})
In case you need to loop on items for specific reason to handle urls then try the code below
var Server = require('../models/server');
Server.find(function(err, items) {
if (err) {
return console.log(err)
} else {
items.forEach(function(item) {
var query = { url: item.url }
Server.update(query, { $set: { updated_at: Date.now() } }, function(err, doc) {
if (err) return console.log(err)
console.log(doc)
})
})
}
})
Mongodb Connection:
var secrets = require('./secrets');
var mongoose = require('mongoose');
module.exports = function() {
var connect = function() {
var mongoLink = "";
if (process.env.NODE_ENV === 'production') {
mongoLink = secrets.db.prod;
} else {
mongoLink = secrets.db.dev;
}
mongoose.connect(mongoLink, function(err, res) {
if (err) {
console.log('Error connecting to: ' + mongoLink + '. ' + err);
} else {
console.log('Connected to: ' + mongoLink);
}
});
};
connect();
mongoose.connection.on('error', console.log);
mongoose.connection.on('disconnected', connect);
}
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 using sails JS.
I have methods like this
beforeDestroy: function(borrow, next){
return Book.find({id:borrow.product})
.then(function(){
Book.update(borrow.product, {'isBorrowed' : false})
})
.then(function(){
next();
})
.catch(function(error){
next(error);
});
}
When I tried to destroy data book 'IsBorrowed' still true, how to fix this when tried t delete data, firstly find id and secondly, change data book IsBorrowed to be false? Thank Advance
Here is a solution (to your original question - just switch the isBorrowed logic around as you now need it):
book.js
module.exports = {
schema: true,
attributes: {
name: {type: 'string', required: true},
desc: {type: 'text'},
isBorrowed: {type: 'boolean', defaultsTo: false}
}
};
bookBorrowed.js
module.exports = {
schema: true,
attributes: {
book: {model: 'Book'}
},
beforeDestroy: function (criteria, next) {
var bookId = criteria.where.id;
console.log(bookId);
Book.update({id: bookId}, {isBorrowed: true})
.exec(function (err, updatedBook) {
if (err) {
next('no book..');
}
console.log('updated book', updatedBook);
next();
});
}
};
Your problem was that you should consider the relationship with id, not object.
Also, the criteria parameter passed into beforeDestroy has a where object, it isn't the model. Also, the update() function takes an object criteria, see above.
If you wish to test, replace your bootstrap.js with the following snippet:
module.exports.bootstrap = function (cb) {
var bk = {name: 'name', desc: 'desc', isBorrowed: false};
Book.create(bk).exec(function (err, book) {
if (err) {
cb(err);
}
console.log('book: ', book);
var bb = {book: book.id};
BookBorrowed.create(bb).exec(function (err, bkBorrowed) {
if (err) {
cb(err);
}
console.log('bkBorrowed: ', bkBorrowed);
BookBorrowed.destroy({id: bkBorrowed.id}).exec(function (err, bkBorrowed) {
if (err) {
cb(err);
}
cb();
});
})
});
};
This is my controller, one form send here the data:
exports.addrepair = function(req, res, next){
Person.findById( req.body.id, function (err, Person) {
Person.update({id: req.body.id},
{$pushAll: {
problem: req.body.problem
, solution: req.body.solution
, date_on: Date.now()
}}
,{upsert:true},function(err){
if(err){
console.log(err);
}else{
console.log("Added");
}
})
})
}
the schema is:
var Person = new Schema ({
name: String,
Repair: [
problem: String,
solution: String,
date_on: Date
]
})
and cant push any repair to Person. With console.log i can see all works but not the push.
This works for me now. Thanks Peter Lyons
Person.findByIdAndUpdate(req.body.id,
{ $push:
{ repair:
{ problem: req.body.problem
, solution: req.body.solution
, date_on: Date.now()
}
},
function(err){ if(err){
console.log(err)
} else {
console.log('Added')
}
});
exports.addrepair = function(req, res, next) {
//The Person.findById you had here was unnecessary/useless
Person.findByIdAndUpdate(req.body.id,
{
Repair: {
$push: {
problem: req.body.problem,
solution: req.body.solution,
date_on: Date.now()
}
}
},
//You don't want an upsert here
function(err){
if(err){
console.log(err);
}else{
console.log("Added");
}
}
)
}