Updating a document with mongoose - node.js

I got a small problem. With this code I updating a existing document in mongodb using node.js and mongoose
router.route('/profile/:profile_id/:session_key')
.put(function(req, res) {
if (req._body == true && req.is('application/json') == 'application/json' ) {
// Get the profile to update
Profile.findOne({ profile_id: req.params.profile_id }, function(err, t_profile) {
if (err) {
res.send(err);
} else {
if(!t_profile) {
res.json({ status: 'CANT FIND PROFILE TO UPDATE' });
} else {
if (t_profile.session_key == req.params.session_key) {
// Update profile with new data
t_profile.name = setReq( t_profile.name, req.body.name );
t_profile.sex = setReq( t_profile.sex, req.body.sex );
t_profile.birthdate = setReq( t_profile.birthdate, req.body.birthdate );
t_profile.country = setReq( t_profile.country, req.body.country );
t_profile.password = setReq( t_profile.password, req.body.password );
// save updatd profile
t_profile.save( { _id: profile._id }, function(save_err, u_profile) {
if (save_err) {
res.json({ status: 'DB ERROR' });
} else {
res.json({ status: 'OK' });
}
});
} else {
res.json({ status: 'NOT LOGGED IN' });
}
//res.json({ status: "THIS RUNS"});
}
}
});
} else {
res.json({ status: 'ERROR', msg: 'Not application/json type'});
}
});
But my function inserted as a parameter in the .save() function neve runs, i need to uncomment the line res.json({ status: "THIS RUNS"}); to get som response back to the client. Why is not res.json({ status: 'DB ERROR' }); or res.json({ status: 'OK' }); sent back?

Stupid error, t_profile.save(function(save_err, u_profile) {...} fixed it.

Related

Mongoose post Query Middleware hook trigger twice

I'm using mongoose Model.findOneAndupdate() to find and update my document and there is a post hook on my model schema for which i'm trying to update another document.
The issue i'm facing is post hook is being triggered twice.
My model:
const mongoose = require('mongoose')
const componentSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
component: {
type: String,
required: true
},
message: {
type: String
},
bodyJson: {
type: mongoose.Schema.Types.Mixed
},
question: {
type: String
}
})
componentSchema.post('findOneAndUpdate', function (result) {
console.log('came here')
})
module.exports = mongoose.model('Component', componentSchema)
In my server log i see that came here logged is twice.
update:
try {
await Component.findOneAndUpdate(query, req.body, { new: true }, function (error, doc) {
if (doc) {
return res.status(200).json({ data: doc })
} else if (error) {
return res.status(400).json({ errors: error.message })
} else res.status(404).json({ errors: 'Not found' })
})
} catch (error) {
logger.error('error while updating order: ' + error)
return res.status(400).json({ errors: error.message })
}
moongoose version i'm using is 5.8.11
You are using both await and callback at the same time. This causes the middleware trigger 2 times. Only one of them must be used.
Use either callback:
Component.findOneAndUpdate(query, req.body, { new: true }, function(
error,
doc
) {
if (err) {
return res.status(400).json({ errors: error.message }); //500 status code may be better
} else {
if (doc) {
return res.status(200).json({ data: doc });
} else {
res.status(404).json({ errors: "Not found" });
}
}
});
Or await:
try {
const doc = await Component.findOneAndUpdate(query, req.body, { new: true });
if (doc) {
return res.status(200).json({ data: doc });
} else {
res.status(404).json({ errors: "Not found" });
}
} catch (error) {
logger.error("error while updating order: " + error);
return res.status(400).json({ errors: error.message });
}

download file using res object in express.js and then send response as true using res.json

I am creating a REST API that will allow the user to download a file when the API is called, the file is getting downloaded but additionally I need to send a a response back using res.json({status : true}) after file is downloaded successfully and deleted from the file system.
I have tried many different ways like using the request module, creating my own middleware, but nothing works. Either file does not get downloaded and response is sent or response is not sent but file is downloaded.
Please find the API code below:
router.route('/generatePdf')
.get((req, res, next) => {
res.json({
status: false,
message: "Invalid Request made"
})
})
.post((req, res, next) => {
try{
let id = req.body.id;
console.log(id + " :this is id"); //I get the mongo ID here
if(id != null && id != ''){
if(validator.isMongoId(id)){
//fetch the data and generate the pdf
myFunctions.fetchInfoById(id, (err, user) => {
if (err) {
console.log('Err in fetchInfoById '+err);
res.json({
status: false
})
} else if (user!= null && user!= '') {
res.render('./referral/referralPdf/PdfTemplate.ejs', {
user: user
}, (err, html) => {
if (err) {
console.log('Err in rendering PDFTemplate ' + err);
res.json({
status: false
})
} else {
let options = {
format: 'A4', // allowed units: A3, A4, A5, Legal, Letter, Tabloid
orientation: 'portrait',
timeout: '100000',
zoomFactor: 0.7
}
pdf.create(html, options).toFile('./public/pdf/' + 'report.pdf', (err, response) => {
if (err) {
console.log('Error in generating pdf' + err);
res.json({
status: false
})
} else {
res.download(response.filename, 'fileContent.pdf', (err) => {
if (err) {
console.log(err);
} else {
fs.unlink(response.filename, (err) => {
if (err) {
console.log(err);
//send response as
res.json({
status : false
})
}else{
console.log('FILE REMOVED!');
res.json({
status : true
})
}
});
}
})
}
})
}
})
} else {
res.json({
status: false
})
}
})
} else {
res.json({
status: false
})
}
} else {
res.json({
status: false
})
}
} catch(e){
console.log("catch " + e);
res.json({
status: false
})
}
})
Please help me with a way of achieving this, I have been at it for hours but could not come up with a better solution.
P.S: with the code above I get error can't set headers after they are sent to the client
The issue I am facing is sending a response back to client once the download is successful and file is deleted from the file system. I am able to use res.render() followed by res.download(). but I am not able to use res.json({status : success}) after download.

MongoDB Update field data

How can i used db.findAndUpdate table user and change my balance from previous amount to newer?
i have try to get balance and the result it show nothing, now i'm confuse to write in findAndUpdate. here's my code:
api:
app.post('/api/account/transfer', (req, res, next) => {
const { body } = req;
const {
sender,
receiver,
amount,
user,
balance,
} = body;
if (!sender) {
return res.send({
success: false,
message: 'Error: Sender cannot be blank!'
});
}
if (!receiver) {
return res.send({
success: false,
message: 'Error: Receiver cannot be blank!'
});
}
if (!amount) {
return res.send({
success: false,
message: 'Error: Fill Amount!'
});
} else if(balance < amount || balance == 0) {
return res.send({
success: false,
message: 'Insufficient funds!'
});
}
//save the new transaction
const newTransaction = new Transaction();
newTransaction.sender = sender;
newTransaction.receiver = receiver;
newTransaction.amount = amount;
newTransaction.save( (err, transaction) => {
if(err) {
return res.send({
success: false,
message: 'Error: Server error.'
});
}else{
return res.send({
success: true,
message: 'Transfer Success!'
});
}
});
//update user balance
User.findOneAndUpdate({
});
and here's the screenshoot:
so what i want is, if i'm as a receiver my balance will be increase.
Try this, the findOneAndUpdate operation does not wait for save operation to complete.
app.post('/api/account/transfer', (req, res, next) => {
const {
body
} = req;
const fields = ['sender', 'receiver', 'amount', 'balance'];
fields.forEach((field) => {
if (!body[field]) {
return res.send({
success: false,
message: 'Error: ' + field + ' cannot be blank!'
});
}
})
if (body.balance < body.amount || body.balance == 0) {
return res.send({
success: false,
message: 'Insufficient funds!'
});
}
//save the new transaction
let newTransaction = new Transaction();
// newTransaction = Object.assign(newTransaction, body); // If you want to copy all params from body to newTransaction
newTransaction.sender = body.sender;
newTransaction.receiver = body.receiver;
newTransaction.amount = body.amount;
newTransaction.save((err, transaction) => {
if (err) {
return res.send({
success: false,
message: 'Error: Server error.'
});
} else {
//update user balance
User.findOneAndUpdate({
/*query*/
}, {
/*body*/
}, (err, data) => {
if (err)
return res.send({
success: false,
message: 'Error: Server error.'
});
return res.send({
success: true,
message: 'Transfer Success!'
});
});
}
});
});

Mongo updating a user

I have a sample piece of Node.js code which pulls a user from the database based on an email, does some checks, does a findOne by ID and updates, like this:
User.findOne({ email }, (err, user) => {
if (err) { return next(err); }
if (!user) {
return res.status(422).send({ error: { message: "User doesnt exists", resend: false } });
}
if (user.auth.used) {
return res.status(422).send({ error: { message: "link already used", resend: false } });
}
if (new Date() > user.auth.expires) {
return res.status(422).send({ error: { message: "link already expired", resend: true } });
}
if (token !== user.auth.token) {
return res.status(422).send({ error: { message: "something has gone wrong, please sign up again", resend: false } });
}
User.findByIdAndUpdate(user.id, { role: 1, auth: { used: true } }, (err) => {
if (err) { return next(err); }
const { email, firstname, lastname } = user;
res.json({ token: tokenForUser(user), email, firstname, lastname });
});
});
Could I not just update and save the user I already have, like this?:
Token.findOne({ token: req.body.token }, function (err, token)
{
if (!token || token !== user.auth.token) return res.status(422).send({ error: { message: "Link doesn't exist or has expired", resend: true } });
// If we found a token, find a matching user
User.findOne({ _id: token._userId }, function (err, user)
{
if (!user) return res.status(422).send({ error: { message: "We couldn't find a user for this token", resend: false } });
if (user.isVerified) return res.status(422).send({ error: { message: "link already used", resend: true } });
// Verify and save the user
user.isVerified = true;
user.save(function (err)
{
if (err) { return res.status(500).send({ msg: err.message }); }
res.json({ token: tokenForUser(user), req.user.email, req.user.firstName, req.user.lastName, req.user.company })
});
});
});

Value not being updated in DB, node.js and mongoose

I am trying to update the value of my model and it does not work.
The weird thing is that I am printing out the result and it looks different than what I see in my database by using Robomongo.
Any thoughts why this happens?
Here is my code:
exports.create = function(req, res) {
var productId = req.query.product;
if (productId) {
Request.createWizard(req.user, { productId: productId }, function(err, request) {
Product.findById(productId, function(err, product) {
if (err) {
return console.log('oh no! error', err);
} else {
if (product.price =! 0 )
request.status = 'ready';
console.log(request);
(Here I see in the terminal: status = ready)
}
});
req.flash('success', { msg: 'Your request has been successfully created.' });
res.redirect('/discover');
});
} else {
var pages = require('../../schemas/wizard/request')();
res.render('requests/form', {
title: 'Make a Request',
pages: pages,
saveState: false
});
}
};
When I am checking the database status is still on pending.
You're changing the status property, but you're not saving the document back to the database after doing so:
Request.createWizard(req.user, { productId: productId }, function(err, request) {
Product.findById(productId, function(err, product) {
if (err) {
return console.log('oh no! error', err);
} else {
if (product.price !== 0) {
request.status = 'ready';
request.save(function(err) { // <-- save it back to the database
if (err) {
console.log('oh no! error', err);
} else {
console.log(request);
}
});
}
}
});
req.flash('success', { msg: 'Your request has been successfully created.' });
res.redirect('/discover');
});

Resources