Mongoose not updating the MongoDB document - node.js

Here is the nodejs code I'm using to update the document in the mongoDB, req.body contains the document which was send as an post request to the nodejs server,
it is not throwing any errors but not updating the document too, any suggestions why this is happening;
router.route('/results').post(function(req,res){
var toupdate = req.body;
delete toupdate._id;
console.log(toupdate)
Question.update({_id:req.body._id}, toupdate, function(err){
if(err){
console.error(err.stack);
}
});
// even tried Question.update({_id:req.body._id}, {$set:{questions:toupdate.question}});
});
I also tried using findById and then saving the document this time got 500 as an response:
router.route('/results').post(function(req,res){
var toupdate = req.body;
delete toupdate._id;
console.log(toupdate)
Question.findById(eq.body._id, function (err, tank) {
if (err){
console.log(err.stack);
return handleError(err);
}
toupdate.save(function (err){
if (err){
console.log(err.stack);
return handleError(err);
}
});
});
});

Thanks for the support, tried your solution JohnnyHK but it didn't work, but found a way to update the document, had to assign fields of req.body to the fields of an object, here :
router.route('/results').post(function(req,res){
Question.findOne(req.body._id, function (err, questions) {
if (err) return handleError(err.stack);
questions.question = req.body.question;
questions.options = req.body.options;
questions.difficulty = req.body.difficulty;
questions.type = req.body.type;
questions.answer = req.body.answer;
questions.domainof = req.body.domainof;
questions.topic = req.body.topic;
questions.weightage = req.body.weightage;
questions.created_by = req.body.created_by;
questions.save(function (err){
if (err) return handleError(err.stack);
console.log(questions);
});
});
});

Related

model.update() not updating

I'm trying to add a new element to an array.
This is the code:
var findEditThenSave = function(personId, done) {
var foodToAdd = 'hamburger';
var foodArray = [];
Person.findById(personId, function (err, data) {
if (err) return console.log(err);
done(null, data);
foodArray = data.favoriteFoods;
console.log("foodArray inside findById: ", foodArray);
foodArray.push(foodToAdd);
var updateObj = {favoriteFoods: foodArray};
console.log(updateObj)
Person.update({_id: personId}, updateObj, function(err, raw) {
if (err) {
console.log("There was an error");
}
console.log("Updated successfully");
console.log("foodArray inside update function:", foodArray);
});
});
};
This is the whole code on Glitch: https://glitch.com/edit/#!/holly-maroon-pony?path=myApp.js%3A226%3A0
This is the console log for a POST request:
POST
foodArray inside findById: ["spaghetti"]
{ favoriteFoods: ["spaghetti","hamburger"] }
(node:8943) DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.
Updated successfully
foodArray inside update function: ["spaghetti","hamburger"]
You can use async and await while making these updates.
var findEditThenSave = async function(personId, done){
var foodToAdd = 'hamburger';
var foodArray = [];
var updateObj;
try{
var data=await Person.findById(personId);
done(null, data);
foodArray = data.favoriteFoods;
console.log("foodArray inside findById: ", foodArray);
foodArray.push(foodToAdd);
updateObj = {favoriteFoods: foodArray};
console.log(updateObj)
}catch(err){
console.log(err);
}
try{
await Person.update({_id: personId}, updateObj);
console.log("Updated successfully");
console.log("foodArray inside update function:", foodArray);
}catch(err){
console.log(err);
}
};
As you can see in your console:
(node:8943) DeprecationWarning: collection.update is
deprecated. Use updateOne, updateMany, or bulkWrite instead.
Updated successfully
So you can get through this using Person.updateOne instead of Person.update
Hope it helps
If you are just planning to update a document and return the updated document you can do something like this
function update(personId) {
var foodToAdd = "hamburger";
const person = Person.findByIdAndUpdate(
personId,
{ $push: { favoriteFoods: foodToAdd } },
{ new: true },
function (err, result) {
if (err) console.log(err);
else console.log(result);
}
);
};

Duplicate mongoose Documents

I'm looking for a very simple way to duplicate a document in my DB but can't find a way to do it.
I have 2 models with the exact same schema.
What i'm doing is
1stDB.findOne({id:"1"}, function(error, results){
if(!error){
var 2ndb = new 2nDB(results);
2nd.save(function (err) {
if (err) {
return err;
}
else {
console.log("SUCCESSFULL");
}
});
}
})
There seems to be an issue as in my console results is formatted properly but just wont save.
But if i do it manually : 2ndb.anyfield = anyvalue it works.
I think it might have to do with promise ? but i'm not very familiar with the concept and might be wrong.
I've tried this :
1stDB.findOne({id:"1"}, function(error, results){
if(!error){
var 2ndb = new 2nDB(**{results}**);
2nd.save(function (err) {
if (err) {
return err;
}
else {
console.log("SUCCESSFULL");
}
});
}
})
and this ( In the hope that deleting the _id and keeping my custom .id field to identify similar document but still having an uniq _id by document would work but it didn't )
1stDB.findOne({id:"1"}, function(error, results){
if(!error){
**var objectResponse = results;
delete objectResponse._id;**
var 2ndb = new 2nDB(results);
2nd.save(function (err) {
if (err) {
return err;
}
else {
console.log("SUCCESSFULL");
}
});
}
})
You can use the following to achieve the required results
1stDB.findOne({id:"1"}).lean().exec(function(error, results){
if(!error){
var objectResponse = results;
delete objectResponse._id;
var 2ndb = new 2nDB(objectResponse);
2nd.save(function (err) {
if (err) {
return err;
}
else {
console.log("SUCCESSFULL");
}
});
}
})
If the lean option is not used, mongoose will return a mongoose object instead of a simple json. This is why you were not able to pass the result directly to the constructor of the 2nd schema. Using the lean query the response will be a plain JSON object which can be passed to the constructor of the 2nd schema. For more information check this stackoverflow post on returning a plan object as response from mongoose

Nodejs+Mongoose : find and update

I'm trying to search for a document in my mongo database then using the found document data to search another document and then update both. First document is to be saved after the second document is found.
But with my code the first document saves but doesnot saves updated data
My code :
var posts = {};
Posts.findOne({'url': req.body.url}, function(err, data){
posts = data;
//console.log(data);
Comments.findOne({'bucket': posts.bucket}, function(err, data){
var comment= data;
if(data.count>10){
posts.bucket = posts.bucket +1;
comment.bucket = comment.bucket +1;
}
comment.save(function(err, data){
if(err)
throw err;
});
});
posts.save(function(err, data){
if(err)
throw err;
res.json(data);
});
});
I observed that whatever changes is done in posts variable in Comments.findOne({...}) it remains local to it and doesnot effect outer posts varible, but it is just declared once. so how can i do this. Is something wrong in code? How do I do this!
First document is to be saved after the second document is found.
In your code you're saving the comment and the post in a parallel manner, you need to save the post after saving the document :
var posts = {};
Posts.findOne({
'url': req.body.url
}, function(err, data) {
posts = data;
//console.log(data);
Comments.findOne({
'bucket': posts.bucket
}, function(err, data) {
var comment = data;
if (data.count > 10) {
posts.bucket = posts.bucket + 1;
comment.bucket = comment.bucket + 1;
}
comment.save(function(err, data) {
if (err)
throw err;
posts.save(function(err, data) {
if (err)
throw err;
res.json(data);
});
});
});
});
Another important remark: you're creating a callback hell which leads to unknown behavior later. Please use async or promises instead of nesting callbacks.

Mongoose: Populate after find()

I'm new to mongo and node js, here's what I'm trying to do:
The API is to check if there is an existing entry in the DB, based on the query.
(a) If no existing document, create a new document, populate, send to
client.
(b) If document exists, return the document, populate, send to
client.
Problem: In scenario (a), after creating document, the API sends "null" to the client.
Suspect: .populate() & .exec() runs before the API finishes creating a new document. The snippet from the code returns null:
console.log('Inside IF' + video_res); // returns null
What's the best way to resolve this?
model_video.findOne( video_entry,
function(err, video_req) { // Send Back Object ID
if (err) res.send(err);
if (!video_req) { // Does not work
console.log('-----STATUS : No Video Found');
model_video.create(video_entry, function(err, video_res) {
console.log('Call back activated');
if (err) res.send(err);
console.log('Response is ' + video_res);
return video_res; // Does not work here!
}); // Ends - Create
console.log('Inside IF ' + video_res);
}
else { // Works
console.log('-----STATUS : Video Found')
if (err) return res.send(err);
var video_res = video_req;
console.log('Response is ' + video_res);
return video_res;
};
})
.populate('_chirps')
.exec(function(err, video_res) {
if (err) return res.send(err);
res.json(video_res);
console.log('Final Output is ' + video_res)
});
};
Your help is greatly appreciated!
The callback exec() callback executes immediately after your .findOne query, you need to put the rest of your code in that callback. I've refactored your code to make it more inline with what you're trying to do.
model_video.findOne(video_entry)
.populate('_chirps')
.exec(function(err, video_res) {
if (err) return res.send(err);
if (video_res) {
console.log('-----STATUS : Video Found')
console.log('Response is ' + video_res);
res.json(video_res)
}
else {
console.log('-----STATUS : No Video Found');
model_video.create(video_entry, function(err, new_video_res) {
if (err) return res.send(err);
console.log('Response is ' + new_video_res);
res.json(new_video_res);
});
}
})

res.redirect() not working for me in node.js

I am trying to POST a request for /draft and create a new "draft" / update an existing one in my database. after that I want to instantly redirect to the /draft?id=RELEVANT_ID_HERE page.
this is my current POST request function:
app.post('/draft', function(req,res){
var id = req.query.id;
var postTitle = req.body.head;
var article = req.body.article;
if(id){
db.postCatalog.findOneAndUpdate({_id: id}, {title:postTitle, inShort:article.substring(0,100), content:article}, function(err, data){
if (err) {
return handleError(err);
}
else {
console.log(data);
res.status(200).redirect('/draft?id='+id);
}
});
}
else{
id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
new db.postCatalog({title:postTitle,
_id:id,
author:'temp',
AuthorID:2,
date:'2/3/12',
inShort:article.substring(0,100),
content:article ,
published:false
}).save(function (err, data) {
if (err) {
return handleError(err);
}
else {
console.log(data);
res.status(200).redirect('/draft?id='+id);
}
});
}
});
so, everything works except for the redirect. I am getting the correct GET request in the node console, but nothing happens in the browser.
this is the code for the GET request:
app.get('/draft', function(req,res){
var id = req.query.id;
if(id){
db.postCatalog.findOne({_id: id}, function(err, post){
if(err) {
return handleError(err);
}
else{
if(post){
console.log(post);
res.status(200).render('editDraft.hbs', {post: post});
}
else{
routes._404(req,res);
}
}
});
}
else{
console.log('creating new draft');
res.status(200).render('editDraft.hbs');
}
});
I am using Express and Mongoose. view engine is Handlebars.
Thanks for reading!
I think the status 200 is throwing you off. Try using a 302 and it should work.
res.writeHead(302, {
'Location': '/draft?id='+id
});
res.end();

Resources