Updating DB Shema in Express JS with Mongoose library - node.js

I have created a Mongo DB schema with Mongoose in Express.js and I am building the REST API. However when I try to update existing records the values that I do not update from the schema automatically become null. I understand why this happens just not sure exactly how it should be coded.
This is the route:
router.patch("/:projectId", async (req, res) => {
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
{
$set: {
title: req.body.title,
project_alias: req.body.project_alias,
description: req.body.description
}
}
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
also here is the schema:
const ProjectsSchema = mongoose.Schema({
title: {
type: String,
required: true,
unique: true
},
project_alias: {
type: String,
unique: true,
required: true
},
description: String,
allowed_hours: Number,
hours_recorded: {
type: Number,
default: 0
},
date_added: {
type: Date,
default: Date.now
}
});
My problem is that when I want to update just the title:
{
"title" : "Title Updated33"
}
description and alias become null. Should I implement a check?

Just use req.body for the update object like this:
router.patch("/:projectId", async (req, res) => {
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
req.body
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
Or even better, create a helper function like this so that we can exclude the fields in the body that doesn't exist in the model:
const filterObj = (obj, ...allowedFields) => {
const newObj = {};
Object.keys(obj).forEach(el => {
if (allowedFields.includes(el)) newObj[el] = obj[el];
});
return newObj;
};
router.patch("/:projectId", async (req, res) => {
const filteredBody = filterObj(
req.body,
"title",
"project_alias",
"description",
"allowed_hours",
"hours_recorded"
);
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
filteredBody
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});

Related

Axios Patch Request showing params as undefined in the backed

I want to update data in the server with a Axios Patch call and there seems to be some error in the code which i cant seem to figure out. Help me out please.
Node express API call in the backend:
router.patch('/up',async (req, res) => {
try{
const id = req.query.userid; // User objectid here.
console.log(req.body)
console.log(req.query.userid)
const result= User.findById(id, (error, foundUser) => {
if (foundUser) {
const { products } = foundUser;
const filteredproducts = products.filter((item) => {
return item._id!= req.body.body._id; //product array object id
});
while (foundUser.products.length > 0) {
foundUser.products.pop();
}
foundUser.products = filteredproducts;
foundUser.products.push({
brandname: req.body.brandname,
productname: req.body.productname,
quantity: req.body.quantity,
price: req.body.price,
description: req.body.description
});
foundUser.save();
}
else
{
console.log('User not found')
}
})
res.status(200).send("update successfull");
}
catch(err){
res.status(403).send('update unsuccessfull')
console.log(err)
}
})
Userschema in db:
const userschema = new mongoose.Schema({
username: {
type: String,
},
email: {
type: String,
required: true
},
place: {
type: String,
required: true
},
password: {
type: String,
required: true
},
products:[
{
brandname: {
type:String,
required:true
},
productname:{
type:String,
required:true
},
quantity:{
type:Number,
required:true
},
price:{
type:Number,
required:true
},
description:{
type:String,
required:true
}
}
]
,
tokens:
[{
token: {
type: String,
required: true
}
}
]
})
const User = mongoose.model('USER', userschema)
Front end API code
const updateproduct = async(req,res) => {
console.warn(values.brandname, values.productname,values.quantity, values.price,
values.description)
console.warn("userlogin is:,",userid) // User object id here.
const _id=id; // Product object id here
await axios.patch(`http://localhost:5000/up`,{
headers: {
'Content-type': 'application/json'
},
data: {brandname,productname,quantity,price,description,_id}, //getting the values of all the fields here. checked by console logging them.
params:{
'userid':userid
}
},
{ withCredentials: true })
.then((res) => {
console.log(res)
navigate('/listproduct')
})
.catch((err) => {
console.log(err)
})
}
Sorry if my code look really bad. I am new to React and node.
All i wanna do is edit the product details of a product by the product objectid and store it in the db.
Any other method other than this is also fine. I am stuck with this problem for more than 2 days coudn't find a solution till now. Any help is much Appreciated.
EDIT:
I have tried to update the code but still the same errors.
backend API
router.patch('/up',async (req, res) => {
try{
const id = req.query.userid;
console.log("user id is",id)
console.log("req.body",req.body.body.brandname)
const result= User.findById(id, (error, foundUser) => {
if (foundUser) {
const { products } = foundUser;
const filteredexpenses = products.filter((item) => {
return item._id!= req.body.body._id;
});
while (foundUser.products.length > 0) {
foundUser.products.pop();
}
foundUser.products = filteredexpenses;
foundUser.products.push({
brandname: req.body.body.brandname,
productname: req.body.body.productname,
quantity: req.body.body.quantity,
price: req.body.body.price,
description: req.body.body.description
});
foundUser.save();
}
else
{
console.log('User not found')
}
})
res.status(200).send("update successfull");
}
catch(err){
res.status(403).send('update unsuccessfull')
console.log(err)
}
})
Front end API
const updateproduct = async(req,res) => {
console.warn(values.brandname, values.productname,values.quantity, values.price, values.description)
console.warn("userlogin is:,",userid)
const _id=id;
await axios.patch(`http://localhost:5000/up`,{
headers: {
'Content-type': 'application/json'
},
body:
{'brandname':brandname,'productname':productname,'quantity':quantity,'price':price,'description':description,'_id':_id},
params:{
'userid':userid
}
},
{ withCredentials: true })
.then((res) => {
console.log(res)
navigate('/listproduct')
})
.catch((err) => {
console.log(err)
})
}
Result on console log is
User id is undefined
req.body adidas //brandname
User not found
Try to change your axios request passing all parameters in the body like this:
await axios
.patch(
`http://localhost:5000/up`,
{ brandname, productname, quantity, price, description, _id, userid },
{
headers: {
'Content-type': 'application/json',
},
},
{ withCredentials: true }
)
.then((res) => {
console.log(res);
navigate('/listproduct');
})
.catch((err) => {
console.log(err);
});
And handle the end point like this:
router.patch('/up', async (req, res) => {
try {
const id = req.body.userid;
User.findById(id, async (error, foundUser) => {
if (foundUser) {
const { products } = foundUser;
const { brandname, productname, quantity, price, description, _id } =
req.body;
const filteredexpenses = products.filter((item) => {
return item._id != _id;
});
while (foundUser.products.length > 0) {
foundUser.products.pop();
}
foundUser.products = filteredexpenses;
foundUser.products.push({
brandname,
productname,
quantity,
price,
description,
});
await foundUser.save();
res.status(200).send('update successfull');
} else {
console.log('User not found');
res.status(400).send('User not found');
}
});
} catch (err) {
res.status(403).send('update unsuccessfull');
console.log(err);
}
});

cant update in mongoDb with mongoose

I am trying to create a followers/following function in my project. However I cannot seem to update the DB correctly. I'm able to send the ids as they both print when I console.log but nothing in my DB updates and I do not get any response in my frontend.
route
app.put('/api/follow', async function (req, res, next){
const { id } = req.query;
const userFrom = req.body.data
console.log('OTHER USER ID',id)
console.log('CURRENT ID', userFrom)
User.findByIdAndUpdate(id), {
$push:{followers:req.body.data}
},{new:true},
(err,result)=>{
if(err) {
if(err) return res.status(400).send(err)
}
User.findByIdAndUpdate(req.body.data), {
$push:{following:id}
},{new:true}.then(result=> {
res.json(result)
}).catch(err=>{
return res.status(422).json({error:err})
})
}
})
user model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
phoneNo: String,
bio: String,
filePath: String,
following: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
followers: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
})
);
module.exports = User;
my route end function
const clickHandler = () => {
const currentID = currentUser.id;
const id = this.props.id;
console.log('CURRENT ID',currentID)
console.log('otherUserID',id)
Axios.put(`http://localhost:8080/api/follow/?id=${id}`, { data: currentID }, { headers: authHeader() })
.then(response => {
if (response.data.success) {
console.log('FOLLOWED', response.data)
// this.setState({ userDetails: response.data.details })
} else {
alert('Error')
}
})
}
This should be
User.findByIdAndUpdate(id, {
You should not close the bracket after id but after new: true})

FindOneAndUpdate overriding and updating only the first id

I am simply trying to update the content according to the id, but whichever id I am using, it updates only the first id by overriding it.
The flow goes as routes => controller => repository
Following is the code:
Routes =>
router.post("/:pageId/content", async (req, res, next) => {
try {
const pageId = req.params;
const pageContent = req.body;
if (!pageId || !pageContent) {
throw {
statusCode: 200,
customMessage: "All parameters are required"
};
}
const result: any = await webpageController.createContent(
pageId,
pageContent
);
if (result.isError) {
throw result.error;
}
res.status(200).json(result.data);
} catch (error) {
next(error);
}
});
Controller =>
const createContent = async (pageId: any, pageContent: any) => {
try {
// calls repository to create content
const result = await webpageRepository.createContent(pageId, pageContent);
// if result is not success, throw error
if (!result.success) {
throw {
statusCode: 400,
customMessage: "Unable to create web page content"
};
}
return {
isError: false,
data: result.data
};
Repository =>
export const createContent = async (pageId: any, content: any) => {
try {
const result = await webpage.findOneAndUpdate(pageId, { content });
return {
data: result,
success: true
};
} catch (error) {
logger.error(
`at:"repositories/webpage/createContent" => ${JSON.stringify(error)}`
);
return {
success: false
};
}
};
Here it can be seen that the id I have used in the route and the id getting updated is different.
What am I doing wrong here?
Following is the schema:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const webpage = new mongoose.Schema(
{
name: {
type: String,
required: true,
trim: true,
maxlength: 25,
},
slug: {
type: String,
// required: true,
},
url: {
type: String,
required: true,
unique: true
},
content: Object,
},
{
timestamps: true,
},
);
export default mongoose.model('webpages', webpage);
I think you should use a dictionary as the parameter.
const result = await webpage.findOneAndUpdate({_id:pageId.pageId}, {content});
You can check on this documentation about how to use the "findOneAndUpdate" https://mongoosejs.com/docs/tutorials/findoneandupdate.html#getting-started
This worked for me
const result = await webpage.findOneAndUpdate( {_id:pageId.pageId} , { content });

mongoose only insert id, createdAt and updated fields

I'm learning to use Node.js and MongoDB. I have a problem when I try to save data to the database.
Here's my code
const Test = require('../models/test');
const test = (req, res, next) => {
let url = "http://localhost:3000/article"
request(url, (req, (err, fields) => {
if (err) {
return res.status(400).json({
error: "error"
})
}
var objTest = JSON.parse(fields.body);
console.log(objTest.user)
let test = new Test(objTest)
console.log("ini",test)
test
.save()
.then(result => {
res.send(result)
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}))
}
here my Test Schema
const testSchema = new mongoose.Schema(
{
tittle: {
type: String,
index: true,
},
content: {
type: String,
},
postedBy: { type: mongoose.Schema.ObjectId, ref: 'Author' },
created: {
type: Date,
default: Date.now,
},
},
{
timestamps: true,
},
);
module.exports = mongoose.model('Test', testSchema, 'tests');
The response in Postman is only id, createdAt and updatedAt. Thank you.

Mongo/Mongoose field value aren't updated

I have a problem with my MongoDB collection. If i try to replace field in my item it won't get saved. It logs new value correctly, but nothing in DB really changes. What's wrong here?
exports.update = function (req, res) {
const { entryid, userid } = req.params;
let field;
['stop', 'description'].forEach(item => req.query[item] ? field = item : -1);
db.TimeEntry.findById(entryid).then(function (entry) {
(req.query[field] === undefined) ? entry[field] = 'no value specified' : entry[field] = req.query[field];
console.log('v:', entry[field]);
entry.save(function (err) {
if (err) console.log(err);
db.TimeEntry.find({ userId: userid })
.then(foundEntries => res.status(200).json(foundEntries));
});
}).catch(err => console.log(err));
}
Schema:
const mongoose = require('mongoose');
const TimeEntrySchema = new mongoose.Schema({
start: {
type: mongoose.Schema.Types.Mixed,
default: Date.now,
required: true
},
stop: mongoose.Schema.Types.Mixed,
description: String,
project: String,
billable: Boolean,
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
}
}, { timestamps: true })
TimeEntrySchema.pre('remove', function (next) {
User.findById(this.userId).then(user => {
user.entries.remove(this.id);
user.save().then(function (e) {
next();
}).catch(err => console.log(err));
})
});
const TimeEntry = mongoose.model('TimeEntry', TimeEntrySchema);
module.exports = TimeEntry;
Edit: Modified this way, still no effect.
` entry[field] = (!req.query[field]) ? 'TESTINGTESTING' : req.query[field];
entry.markModified('description');
console.log('v:', entry[field]);
entry.save().then(function (err) {`
Final edit: Ok so this is the final solution.
exports.update = function (req, res) {
const { entryid, userid } = req.params;
let field;
['stop', 'description'].forEach(item => req.query[item] ? field = item : -1);
db.TimeEntry.update({ _id: entryid }, {
$set: {
description: req.query[field] || 'no value specified'
}
}).then(function () {
db.TimeEntry.find({ userId: userid })
.then((foundEntries) => res.status(200).json(foundEntries))
}).catch(err => console.log(err));
}
Try using .update:
return db.TimeEntry.update({ _id: entryid }, {
$set: {
[field]: req.query[field] || 'no value specified'
}
}
}).then(() => db.TimeEntry.find({ _id: entryid }))
.then((resultEntries) => res.status(200).json(foundEntries))
Have you tried this: entry.save().exec(callbackFN);
instead of entry.save(callbackFN); ?

Resources