In my application, I have an Model say it is Record, and a Record may have several Attachment which can be uploaded to the server.
Generally, when creating a Record with Attachment(files), I will upload and save the files first, then save the record, like this:
function createOrUpdateInfo(req, res, next) {
var record = req.body;
var attachmentIds = (record.files || []).map(function (a) {
return a.id;
});
var attachmentFilter = {
where: {
id: {
$in: attachmentIds || []
}
}
};
DB.sequelize.transaction(function (t) {
var pro;
if (record.id) {
//update
//update the basic information first
return Record.update(record, {
where: {
id: req.params.id
}, transaction: t
}).then(function (num, infos) {
//find the record just saved.
return Record.findById(req.params.id).then(function (record) {
//find the attachmens which have been saved
return Attachment.findAll(attachmentFilter).then(function (atts) {
//update the record, create the association.
return record.setFiles(atts, {transaction: t});
});
})
});
} else {
//save
return Record.create(record, {transaction: t}).then(function (record) {
return Attachment.findAll(attachmentFilter).then(function (atts) {
return record.setFiles(atts, {transaction: t});
});
});
}
}).then(function (result) {
Util.sendJson(res, result)
}).catch(function (err) {
next({message: err.message, code: 500});
});
}
As shown, there are too many nested callbacks when create or update a Record.
Is this can be fixed?
I've reorganized your code a bit. Hope it helps.
function createOrUpdateInfo(req, res, next) {
var record = req.body;
var attachmentIds = (record.files || []).map(function (a) {
return a.id;
});
var attachmentFilter = {
where: {
id: {
$in: attachmentIds || []
}
}
};
DB.sequelize.transaction(function (t) {
var pro;
return (function () {
if (record.id) {
//update
//update the basic information first
return Record.update(record, {
where: {
id: req.params.id
}, transaction: t
}).then(function (num, infos) {
//find the record just saved.
return Record.findById(req.params.id);
});
} else {
//save
return Record.create(record, {transaction: t});
}
}()).then(function () {
//find the attachmens which have been saved
return Attachment.findAll(attachmentFilter);
}).then(function (atts) {
//update the record, create the association.
return record.setFiles(atts, {transaction: t});
});
}).then(function (result) {
Util.sendJson(res, result)
}).catch(function (err) {
next({message: err.message, code: 500});
});
}
Related
my code below works just fine and updates or creates documents, but does not return status code 200 it just waits without any return value, any idea why this is happening
exports.flagUser = async (req, res) => {
try {
const user = await FlaggedUser.findOne({ userId: req.body.userId });
if (user) {
if (user.flaggedBy.includes(req.body.flaggedBy.toString())) {
print("error");
return res.status(500);
} else {
console.log("user found");
await user.updateOne({
$inc: { flagCount: 1 },
$addToSet: { flaggedBy: req.body.flaggedBy },
});
return res.status(200);
}
} else {
const flaggedUser = new FlaggedUser({
_id: new mongoose.Types.ObjectId(),
userId: req.body.userId,
flagCount: 1,
flaggedBy: [req.body.flaggedBy],
});
await flaggedUser.save();
console.log("flag");
return res.status(200);
}
} catch (error) {
console.log(error);
return res.status(500).json({
...error,
});
}
};
If you want to send just status codes you need to write res.status(num).send(); or res.status(num).end();. Here is the doc to read more up on this http://expressjs.com/en/api.html
I'm using koa to reset a password, wanting to use .save in order to fire the schema.pre('save' ).
data was returning with findOneAndUpdate, but not when I use .save.
what's the magic combination to make this return the .save doc properly with the await/asyncs?
r.post("/public/auth/resetpass", async (ctx, next) => {
const values = ctx.request.body;
const query = {
email: values.email,
resetPasswordToken: values.resetPasswordToken,
resetPasswordExpires: {
$gt: new Date(new Date())
}
};
const update = {
password: values.password,
resetPasswordToken: null,
resetPasswordExpires: null
};
// let userFound = null;
await User.findOne(query,async function(err, user) {
if (err) {
console.log("*** err");
next(err);
} else {
if (_.isEmpty(user)) {
ctx.status = 200;
ctx.body = {
error: true,
message: "token is incorrect or time has expired for password reset"
};
} else {
user.password = values.password;
await user.save(function(err, doc) {
if (err) {
console.log('***err saving');
next(err);
} else {
//console.log fires, but ctx body doesn't return
console.log ('***saved, writing poco');
ctx.body = userToPoco(doc);
}
});
}
}
});
});
ultimately switched to a promise.
await user.save().then (doc =>{
ctx.body = doc;
});
I am using Express node, MongoDB In this App.
Idea: send Post request contains an array of objects, => check if any object is existed before, => add the
not existed elements to the array in the document in one shot.
problem: Each time I sent a post request only one element is added. I have to repeat 3 times in order to add an array of 3 elements.
solution tried: before I used promise.all() nothing has been added. after I used promise.all only one element is added
code:
.post(cors.corsWithOptions, authenticate.verifyUser, (req, res, next) => {
let favstoAdd = req.body.favorites;
let user = req.user;
//check if the user have a favorites already and create favorites if it is not existed
var p1 = Favorites.findOne({ user: user._id })
.then((res_user) => {
if (res_user !== null) {
}
else {
Favorites.create({ user: user._id, favorites: [] });
}
});
//check if the dish Existed before in the favs and add them to the new filtered array
var altered_favstoAdd = [];
var p2 = favstoAdd.map((fav) => {
Favorites.findOne({ favorites: fav._id })
.then((dish) => {
if (dish == null) {
altered_favstoAdd.push(fav);
}
})
.catch((err) => { next(err) });
});
var p3 = promise.all([p1, p2]).then(values => {
//update favorite
for (let i = 0; i < altered_favstoAdd.length; i++) {
let alt_fav = altered_favstoAdd[i];
Favorites.update({ user: user._id }, { $push: { favorites: alt_fav } }, { new: true }, (err, resp) => {
if (err) { next(err); }
})
}
});
//respond with the favorite item
promise.all([p3]).then(
Favorites.findOne({ user: user._id })
.then((favorite) => { res.json(favorite); })
.catch((err) => { next(err) })
)
})
I think the problem is in the map function :
var p2 = favstoAdd.map((fav) => {
Favorites.findOne({ favorites: fav._id })
.then((dish) => {
if (dish == null) {
altered_favstoAdd.push(fav);
}
})
.catch((err) => { next(err) });
});
this function does not itereate over the whole array some thing is preventing it.
any Ideas??
I cannot remove an element inside of an array that is a property of a MongoDB Model.
Please remember this is a NodeJS module mongooseJS and not the real MongoDB so functionalities are not the same..
GOAL: Delete an object from the statusLiked array. | I have also confirmed that the value of status.id is correct.
Model:
Const userSchema = new mongoose.Schema({
myStatus: Array,
statusLiked: Array,
)};
Delete:
1. Deletes the status(works). 2. Delete the status from User.statusLiked(no work).
exports.deleteStatus = (req, res, next) => {
var CurrentPost = req.body.statusid; // sends in the status.id
Status.remove({ _id: CurrentPost }, (err) => {
if (err) { return next(err); }
// vvvv this vvv
User.update( {id: req.user.id}, { $pullAll: {_id: CurrentPost }, function(err) { console.log('error: '+err) } });
req.flash('success', { msg: 'Status deleted.' });
res.redirect('/');
});
};
What happens: The specific status(object) is deleted from the database. But the status still remains in the User.statusLiked array.
What I want to happen: Status to be deleted from the User.statusLiked array and the status to be deleted from the database. Then, reload the page and display a notification.
I got it to work somehow. Working code:
exports.deleteStatus = (req, res, next) => {
var CurrUser = req.body.userid;
var CurrentPost = req.body.post;
Status.remove({ _id: CurrentPost }, (err) => {
if (err) { return next(err); }
console.log('meeee'+CurrentPost+'user: ' +CurrUser);
req.flash('success', { msg: 'Status deleted.' });
res.redirect('/');
});
User.update(
{ _id: new ObjectId(CurrUser)},
{ $pull: { myStatus : { _id : new ObjectId(CurrentPost) } } },
{ safe: true },
function (err, obj) {
console.log(err || obj);
});
};
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');
});