sorting in mongoose is providing random result - node.js

I have a collection named payments with field named 'sorter' in it, I want to sort my results descending with the 'sorter' field
I have no Idea how to do it
return ApiProtectedRoute(
req,
res,
(protectedUserid, protectedUsername, protectedEmail, protectedBalance) => {
paymentModels
.find({
userId: protectedUserid
}, function(err, payments) {
if (payments.length == 0) {
res.status(400).json({
error: true,
message: "No payments found",
info: "getPayments",
});
} else if (payments.length > 0) {
let paymentsWithUsername = [];
payments.forEach((payment) => {
userModels.findOne({
_id: payment.userId
}, function(err, user) {
if (err) console.log(err);
paymentsWithUsername.push({
...payment._doc,
username: user.username,
email: user.email,
});
if (paymentsWithUsername.length === payments.length) {
res.status(200).json({
error: false,
payments: paymentsWithUsername,
info: "getPayments",
});
}
});
});
} else {
res.status(400).json({
error: true,
message: "Something went wrong",
info: "getPayments",
});
}
})
.sort({
sorter: -1
});
}
);
this code shows random result at everytime
Payments collection:

Related

How to Utilize Error and Result Data Callback Simultaneously in Mongoose Express?

I want to use error and result data in my controller, but got a little bit confused and always got this response :
{
"status": "fail",
"message": "Cast to ObjectId failed for value \"60f943dd4bef612ae873d34\" (type string) at path \"_id\" for model \"Student\""
}
But i get this response when the data is not found :
}
"status": "fail",
"message": "Cannot delete student data with id 60f943dd4bef612ae873d34. Student data was not found
}
My code as follows :
deleteOneStudent: async (req, res) => {
const { _id } = req.params;
const student = Student.findById({ _id });
await Student.exists({ _id }, async (err, data) => {
if (err) {
return res.status(500).json({
status: "fail",
message: err.message || "Some error occurred while deleting student data."
});
}
if (!data) {
return res.status(404).json({
status: "fail",
message: `Cannot delete student data with id ${_id}. Student data was not found`
});
} else { //the code below is for removing ref from Semester document when deleting Student document
await Semester.updateMany({ '_id': student.semester }, { $pull: { student: student._id } }, { new: true, useFindAndModify: false })
student.remove()
return res.status(200).json({
status: "success",
message: "Student data was deleted successfully",
});
}
})
},
if I remove the first if, everything works fine, but I want to utilize 404 , 500 , and 200 altogether, and I have no idea using .then() and .catch() either. Can anyone help me? Thanks in advance
It looks _id casting issue. You can wrap _id in mongoose.Types.ObjectId
await Student.exists({ _id:mongoose.Types.ObjectId(_id) }, async (err, data) => {
if (err) {
return res.status(500).json({
status: "fail",
message: err.message || "Some error occurred while deleting student data."
});
}
....
....
deleteOneStudent: async (req, res) => {
try{
const { _id } = req.params;
const student = Student.findById({ _id });
await Student.exists({ _id }, async (err, data) => {
if (err) {
return res.status(500).json({
status: "fail",
message: err.message || "Some error occurred while deleting student data."
});
}
if (!data) {
return res.status(404).json({
status: "fail",
message: `Cannot delete student data with id ${_id}. Student data was not found`
});
} else { //the code below is for removing ref from Semester document when deleting Student document
await Semester.updateMany({ '_id': student.semester }, { $pull: { student: student._id } }, { new: true, useFindAndModify: false })
student.remove()
return res.status(200).json({
status: "success",
message: "Student data was deleted successfully",
});
}
})
}
catch(error){
return res.status(500).json({
status: "fail",
message: error,
});
}
}

how check if user exist in nodejs

I'm making a auth system with nodejs and mongoDB(mongoose) and I get Error:
error: UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at F:\tryMern\index.js:68:13
index.js (important part) :
app.post("/api/auth", (req, res) => {
if (req.body.username && req.body.pass && req.body.status == "new") {
User.find({ username: req.body.username }, (err, users) => {
if (!err) {
if (users.length > 0) {
return res.json({ error: "The username is taken." });
}
}
});
const validReq = validate.validate({
username: req.body.username,
pass: req.body.pass,
});
if (validReq.error) {
return res.json({ error: validReq.error.details[0].message });
}
bcrypt.hash(req.body.pass, 12).then((hashedPass) => {
// console.log(hashedPass);
const user = new User({
username: req.body.username,
password: hashedPass,
});
user.save().then((user) =>
res.json({
status: "OK",
username: user.username,
token: jwt.sign({ _id: user._id }, jwtKey),
})
);
});
return;
}
User.find({ username: req.body.username }, (err, users) => {
if (err) {
console.log(err);
} else {
if (users.length > 0) {
bcrypt.compare(req.body.pass, users[0].password, (err, hash) => {
if (hash) {
return res.json({
validate: true,
username: users[0].username,
token: jwt.sign({ _id: users[0]._id }, jwtKey),
});
} else {
return res.json({ validate: false });
}
});
} else {
return res.json({ validate: false });
}
}
});
});
when I add The username is taken part the error comes ( the part say find user and if its exist say username is taken)
if there is another way to check if user exist please tell or fix this problem
thanks :)
EDIT:
when i try to submit the user with exist username the response is { "error": "The username is taken." } and the error come
I fix this:
app.post("/api/auth", (req, res) => {
if (req.body.username && req.body.pass && req.body.status == "new") {
User.find({ username: req.body.username }, (err, users) => {
if (!err) {
if (users.length > 0) {
res.json({ error: "The username is taken." });
return;
}
const validReq = validate.validate({
username: req.body.username,
pass: req.body.pass,
});
if (validReq.error) {
return res.json({ error: validReq.error.details[0].message });
}
bcrypt.hash(req.body.pass, 12).then((hashedPass) => {
// console.log(hashedPass);
const user = new User({
username: req.body.username,
password: hashedPass,
});
user.save().then((user) =>
res.json({
status: "OK",
username: user.username,
token: jwt.sign({ _id: user._id }, jwtKey),
})
);
});
}
});
return;
}
User.find({ username: req.body.username }, (err, users) => {
if (err) {
console.log(err);
} else {
if (users.length > 0) {
bcrypt.compare(req.body.pass, users[0].password, (err, hash) => {
if (hash) {
return res.json({
validate: true,
username: users[0].username,
token: jwt.sign({ _id: users[0]._id }, jwtKey),
});
} else {
return res.json({ validate: false });
}
});
} else {
return res.json({ validate: false });
}
}
});
});

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 });
}

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 })
});
});
});

I want to update form data in Node.js, but whenever i run this code it sets all the values to null

app.put('/edit/:id', function(req, res) {
//new actor data
var actor = {
'name': req.body.name,
'dob': req.body.dob,
'photo': req.file,
'bio' : req.body.bio
};
//updating actor
Actor.findOneAndUpdate({ _id:req.params.id }, { $set: actor }, { new: true }, function(err, data) {
if (err) {
res.send({
status: false,
error: err
});
} else {
res.send({
status: true,
data: data
});
}
});
});
I have tried it with post also and taking id through body also but still it is not working.
Tried it on postman as well as on frontend through form also. In postman also it is not able to take data or read data
Try this in order to update the actor :
Actor.findOneAndUpdate({ _id:req.params.id }, {$set: {actor:actor},}, function(err, data) {
if (err) {
res.send({
status: false,
error: err
});
} else {
res.send({
status: true,
data: data
});
}
});

Resources