mongodb database fileds are not updating - node.js

Im trying to update the data , but its not updating in the database
but in console it is showing like this
Here is the code :
exports.forgotPassword = async( req, res) =>{
const { id, password } = req.body;
const user = await User.findOne({ _id : id })
if (!user) {
res.status(200).send({
message: "User was not found"
});
}
else {
const userUpdatedPassword = User.update({id}, {$set:{ password:encrypt(password),
updatedPasswordTime:new Date() }})
res.status(200).send({
message: "Upadted Sucessfully"
});
}
}

I think you put the wrong filter, you need to do const userUpdatedPassword = await User.updateOne({_id: id}, {$set:{ password:encrypt(password), updatedPasswordTime:new Date() }}), in addition you can await for result and print userUpdatedPassword to console to check if here updatedCount > 0.

Related

How to update only specific field in object within an array Mongodb

Expense Tracker application : Nodejs, Mongodb
Trying to Create a function that will update only the passed fields from request inside an array of objects
Database Schema
const updateExpense = async (req, res) => {
try {
let db = mongo.getDb()
let { macro, micro, amount, note } = req.body;
let { username, id } = req.query
let expense = await db.collection("Expense").updateOne({ username: username, "expenses.expense_id": ObjectId(id) }, { $set: {
"expenses.$.macro": macro,
"expenses.$.micro": micro,
"expenses.$.amount": amount,
"expenses.$.note": note }
});
res.status(200).json({
message: "Expense Updated",
expense: expense
});
} catch (err) {
res.status(500).json({
message: err.message
});
}
}
The above function is replacing all other fields with null
If the user is passing only the micro field, then the other fields should remain the same and only the micro field should change and other fields should not change.
Need A MongoDB Query which will only change what is required based on the data passed in req
I think you must first fetch from the database with findOne then update that fields set in req.body, something like this:
const updateExpense = async (req, res) => {
try {
let db = mongo.getDb()
let { macro, micro, amount, note } = req.body;
let { username, id } = req.query
let expense = await db.collection("Expense").findOne({ username: username });
let special_ex = expense.expenses.find(ex => ex.expense_id === ObjectId(id);
special_ex.macro = macro ? macro : special_ex.macro;
special_ex.micro = micro ? micro : special_ex.micro;
/*
and so on ...
*/
await expense.update();
res.status(200).json({
message: "Expense Updated",
expense: expense
});
} catch (err) {
res.status(500).json({
message: err.message
});
}
}

Node.js, Mongoose: Cannot read properties of null (reading 'comparePassword')

I was attempting to updateUserPassword in my userController.js and came across the following error. Unsure what kind of error this could be. Any input and knowledge would be appreciated.
Getting this error on postman
{
"msg": "Cannot read properties of null (reading 'comparePassword')"
}
Body
{
"oldPassword":"secret",
"newPassword":"newsecret"
}
userController.js
const updateUserPassword = async (req, res) => {
const { oldPassword, newPassword } = req.body;
if (!oldPassword || !newPassword) {
throw new CustomError.BadRequestError('Please provide both values');
}
const user = await User.findOne({ _id: req.user.userId });
const isPasswordValid = await user.comparePassword(oldPassword);
if (!isPasswordValid) {
throw new CustomError.UnauthenticatedError('Invalid Credentials');
}
user.password = newPassword;
await user.save();
res.status(StatusCodes.OK).json({ msg: 'Success! Password Updated.' });
};
Github: https://github.com/k4u5hik/node-express-course
You need to check whether the user is exists or not before calling user.camparePassword, for example:
const user = await User.findOne({ _id: req.user.userId });
if (!user) {
throw new CustomError.UserNotFound();
}
const isPasswordValid = await user.comparePassword(oldPassword);

TypeError: newUser.find is not a function

I am very new to the MERN stack and I would like some help figuring out this error. I'm trying to check if an email is already in the database upon creating a new user. Can anyone tell me why I am getting this error?
The model and scheme
//schema
const Schema = mongoose.Schema;
const VerificationSchema = new Schema({
FullName: String,
email: String,
password: String,
date: Date,
isVerified: Boolean,
});
// Model
const User = mongoose.model("Users", VerificationSchema);
module.exports = User;
The Api
const express = require("express");
const router = express.Router();
const User = require("../Models/User");
router.get("/VerifyEmail", (req, res) => {
console.log("Body:", req.body);
const data = req.body;
const newUser = new User();
newUser.find({ email: data.email }, function (err, newUser) {
if (err) console.log(err);
if (newUser) {
console.log("ErrorMessage: This email already exists");
} else {
console.log("This email is valid");
}
});
res.json({
msg: "We received your data!!!",
});
});
module.exports = router;
The api caller using axios
const isEmailValid = (value) => {
const info = {
email: value,
};
axios({
url: "http://localhost:3001/api/VerifyEmail",
method: "get",
data: info,
})
.then(() => {
console.log("Data has been sent");
console.log(info);
})
.catch(() => {
console.log("Internal server error");
});
};
if you have body in your request, change the type of request to POST...
after that for use find don't need to create a instance of model, use find with Model
router.get("/VerifyEmail", (req, res) => {
console.log("Body:", req.body);
const data = req.body;
User.find({ email: data.email }, function (err, newUser) {
if (err) console.log(err);
if (newUser) {
console.log("ErrorMessage: This email already exists");
} else {
console.log("This email is valid");
}
});
res.json({
msg: "We received your data!!!",
});
});
I prefer to use async/await and don't use Uppercase world for routing check the article: like this
router.post("/verify-email", async (req, res) => {
try {
let { email } = req.body;
let newUser = await User.findOne({ email });
if (newUser) {
console.log("ErrorMessage: This email already exists");
} else {
console.log("This email is valid");
}
} catch (error) {
res.json({
msg: "somthing went wrong",
});
}
res.json({
msg: "We received your data!!!",
});
});
The proper way to query a Model is like so:
const User = mongoose.model('Users');
User.find({<query>}, function (err, newUser) {...
So you need to get the model into a variable (in this case User) and then run the find function directly against it, as opposed to running it against an object you instantiate from it. So this is incorrect:
const newUser = new User();
newUser.find(...
So assuming all your files and modules are linked up correctly, this should work:
const User = require("../Models/User");
User.find({<query>}, function (err, newUser) {...
The problem wasn't actually the mongoose function but I needed to parse the object being sent.
let { email } = JSON.parse(req.body);
Before parsing the object looked like {"email" : "something#gmail.com"}
and after parsing the object looked like {email: 'something#gmail.com'}
I also changed the request from 'get' to 'post' and instead of creating a new instance of the model I simply used User.find() instead of newUser.find()

access the info of the user that created the post

I am making a react-native mobile app and I am having trouble passing the users info that created the post to the home page in the post detail. I can pass the userID but for some reason when I add the rest of the info to the payload I can't create a post. Please help.
BACKEND
This is the requireAuth file that requires authentication before performing a tast. My code for the user is here as well at the bottom---
const mongoose = require("mongoose");
const User = mongoose.model("User");
module.exports = (req, res, next) => {
const { authorization } = req.headers;
if (!authorization) {
return res.status(401).send({ error: "You must be logged in." });
}
const token = authorization.replace("Bearer ", "");
jwt.verify(token, "mySecretKey", async (err, payload) => {
if (err) {
return res.status(401).send({ error: "You must be logged in." });
}
const { userId, name, phone, email } = payload;
const user = await User.findById(userId);
req.user = user;
console.log(req.user);
next();
});
};
This is the POST route for the Item---
router.post("/items", requireAuth, async (req, res) => {
const { title, category, detail, condition, price } = req.body;
if (!title || !category || !detail || !condition || !price) {
return res.status(422).send({
error: "You must provide a title, category, detail, condition, and price"
});
}
try {
const item = new Item({
title,
category,
detail,
condition,
price,
userId: req.user._id
});
await item.save();
res.send(item);
} catch (err) {
res.status(422).send({ error: err.message });
}
});
FRONT-END
This is my createItem function in the itemContext file---
const createItem = dispatch => async ({
title,
category,
detail,
condition,
price
}) => {
try {
const response = await sellerApi.post("/items", {
title,
category,
detail,
condition,
price
});
//this is the other place the error might be happening i need this to save in the phone local storage
dispatch({ type: "create_item", payload: response.data });
navigate("Home");
} catch (err) {
console.log(err);
}
};
All I am trying to do it is when the post is being displayed so is the info of the post creator
For existing post in the database: If you are referencing your user in post model like this
const Post = mongoose.model('Post', {
// other fields
userId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
})
then you can use populate to fetch user of that post.
const post= await Post.findById('5c2e505a3253e18a43e612e6')
await post.populate('userId').execPopulate()
console.log(post.userId)

How can I implement transaction concept in mongoose model?

I have three models "userLogin.js","userDetail.js",and "userAddress.js".I want data should be stored simultaneously, if any error occurs it should rolback all the insert actions.this what I have tried. I gives me the error user is not defined . when try to fix them it gives the error "schema is not registered"
const UserLogin=require("../models/userLogin");
const UserDeatil=require("../models/userDetail");
var myModelSchema1 = require('mongoose').model('UserLogin').schema;
var myModelSchema2 = require('mongoose').model('UserDeatils').schema;
exports.user_signup = (req, res, next) => {
UserLogin.find({ email: req.body.email })
.exec()
.then(user => {
if (user.length >= 1) {
return res.status(409).json({
message: "Mail exists"
});
} else {
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).json({
error: err
});
} else {
const user = new UserLogin({
_id: new mongoose.Types.ObjectId(),
email: req.body.email,
password: hash,
loginDate:req.body.logindate,
});
const userdetils = new UserDeatil({
_id: new mongoose.Types.ObjectId(),
userId:result.userID,
userName:req.body.username,
dob:req.body.dob,
gender:req.body.gender,
photo: req.file? req.file.path : null,
imei:req.body.imei,
});
insertUsers();
}
});
}
});
};
async function insertUsers(){
try{
const id= transaction.insert(myModelSchema1, user);
const id1= transaction.insert(myModelSchema2, userdetils);
const final = await transaction.run();
}
catch(error){
console.error(error);
const rollbackObj = await transaction.rollback().catch(console.error);
transaction.clean();
c
}
}
first when you define your users schema the email must be uniqe wich when fails when you tries to create anothe user document with the same email,
and with this convention you can move forward like this:
const UserLogin=require("../models/userLogin");
const UserDeatil=require("../models/userDetail");
cosnt signup = async (req ,res)=>{
const { email , password ,...details} = req.body
const createdDocs = []
const hashedPwd = hash(password);
try{
const user = new UserLogin({ email , password: hashedPwd });
await user.save()
createdDocs.push(user)
const userDetails = new UserDetails({...details,userId:user._id});
await userDetails.save()
createdDocs.push(userDetails)
catch(err){
res.json({ status:false, message:err.message})
//emulates the rollback when any thing fails on the try flow
if(createdDocs.length){
const operationsToRollBack = createdDocs.map(doc=>doc.remove)
await Promise.all(operationsToRollBack)
}
}
MongoDB supports multi-document transactions starting from version 4.0.
Ideally, if you need a transactional database you would use an SQL type db.
But if you would still like to enjoy MongoDB while needing transactions, they have introduced an API for this - https://docs.mongodb.com/manual/core/transactions/

Resources