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);
}
});
Related
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})
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 });
}
});
I am trying to create an Inventory update-route in a MERN stack. My "Add new item" route works perfectly, but the "update route" as refused to update, can someone please tell me what I am doing wrong
//Model
const mongoose= require('mongoose');
const Schema = mongoose.Schema;
//create Schema
const ItemSchema = new Schema({
name : String,
description : String,
price : Number,
quantity : Number,
supplier : String,
taxable : Boolean,
});
module.exports=Inventory=mongoose.model('item',ItemSchema,'inventory');
Routes.js
router.post('/update', (req, res) => {
// inserting a new inventory
var _id = req.body._id;
var inventory = {
name:req.body.name,
description:req.body.description,
price:req.body.price,
quantity:req.body.quantity,
supplier:req.body.supplier,
taxable:req.body.taxable,
};
Inventory.findByIdAndUpdate(_id, { $set: inventory }, { new: true }, function (err, inventory) {
if (err) {
res.status(500);
res.send(err);
} else {
res.status(200);
res.send();
}
});
});
UpdateForm.js
class InventoryUpdateForm extends Component {
constructor(props){
super(props);
this.state = {
_id: this.props.match.params._id,
name: "",
description: "",
price: "",
quantity: "",
supplier: "",
taxable: "",
loading: true,
date: moment(new Date()).format("YYYY-MM-DD"),
};
//some code, basically binding change function with "this"
.........................
//Firstly, I get the entire data for the particular id here
componentWillMount(){
axios.get("/api/inventory/"+this.state._id)
.then(
(res) => {
var newState = {
name: res.data.name,
description: res.data.department,
price: res.data.price,
quantity:res.data.quantity,
supplier:res.data.supplier,
taxable:res.data.taxable,
};
this.setState( newState );
this.setState( { loading: false } );
},
(err) => {
alert('An error occured! Try refreshing the page.', err);
}
);
}
Here i handle the change event cases
handleDatePickerChange(date){
this.setState({ date: moment(date).format("YYYY-MM-DD") });
}
handleNameChange(event){
this.setState({ name: event.target.value });
}
handleDescriptionChange(event){
this.setState({ description: event.target.value });
}
handlePriceChange(event){
this.setState({ price: event.target.value });
handleQuantityChange(event){
this.setState({ quantity: event.target.value });
}
handleSupplierChange(event){
this.setState({ supplier: event.target.value });
}
handleTaxableChange(event){
this.setState({ taxable: event.target.value });
}
And i finally submit
submitForm(){
const { _id, name, description, price, quantity,supplier,taxable} = this.state;
var inventory = {
_id, name, description, price, quantity,supplier,taxable
};
axios.post('/update', inventory)
.then(
(res) => {
alert('Updated successfully!');
},
(err) => {
alert('An error occurred! Try submitting the form again.', err);
}
);
}
The data is retrieved, rendered and I actually update, but when I try to save it I get my error message
back
An error occurred! Try submitting the form again
How do I resolve this?
In axios to catch errors, we add a catch block.
Your submitForm must be like this, can you try and comment what happens?
submitForm() {
const { _id, name, description, price, quantity,supplier,taxable} = this.state;
var inventory = {
_id, name, description, price, quantity,supplier,taxable
};
axios.post('/update', inventory)
.then( res => {
alert('Updated successfully!');
}
)
.catch(err => {
console.log(err.response);
alert('An error occurred! Try submitting the form again.');
});
}
Also in findByIdAndUpdate, there is no need to use $set, you can simply do like this:
router.post("/update", (req, res) => {
console.log("req.body", req.body);
// inserting a new inventory
var _id = req.body._id;
var inventory = {
name: req.body.name,
description: req.body.description,
price: req.body.price,
quantity: req.body.quantity,
supplier: req.body.supplier,
taxable: req.body.taxable
};
Inventory.findByIdAndUpdate(_id, inventory, { new: true }, function(
err,
inventory
) {
if (err) {
console.log("err", err);
res.status(500).send(err);
} else {
console.log("success");
res.send(inventory);
}
});
});
Also can you set the state like this in constructor to match data types in mongoose schema.
this.state = {
_id: this.props.match.params._id,
name: "",
description: "",
price: 0,
quantity: 0,
supplier: "",
taxable: false,
loading: true,
date: moment(new Date()).format("YYYY-MM-DD"),
};
And lastly lets convert our price and quantity number by adding a plus.
handlePriceChange(event){
this.setState({ price: +event.target.value });
handleQuantityChange(event){
this.setState({ quantity: +event.target.value });
}
An alternative is to use the "PUT" method in express.
router.put('/update', (req, res) => {
//Code to update your data
})
I working on Mongoose and Express project where by I have 3 models: User, Album and Purchase. The purchase model references the user and album. I am creating a POST endpoint where by I can make a purchase and then retrieve the data as well as the user and album relations which should be populated with their data, but I am stuck.
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
// TODO: Define Schema
name: {
type: String,
required: true
}
})
var User = mongoose.model('User', userSchema)
var albumSchema = mongoose.Schema({
// TODO: Define Schema
title: {
type: String,
required: true
},
performer: {
type: String,
required: true
},
cost: {
type: Number,
required: true
}
})
var Album = mongoose.model('Album', albumSchema);
var puchaseSchema = mongoose.Schema({
// TODO: Define Schema
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Album'
},
album: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
var Purchase = mongoose.model('Purchase', puchaseSchema);
app.use(bodyParser.json());
app.listen(3000);
// TODO: GET /albums
app.get('/albums', (req,res) => {
Album.find()
.then((response) => {
res.json({data: response})
})
.catch(err => {
res.json({error: err})
})
})
// TODO: GET /albums/:id
app.get('/albums/:id', (req,res) => {
Album.findById(req.params.id)
.then(response => {
res.json({data: response})
.catch(err => {
res.json({Error: err})
})
})
})
// TODO: POST /albums
app.post('/albums', (req,res) => {
const newPost = Album({
title: req.body.title,
performer: req.body.performer,
cost: req.body.cost
})
newPost.save(err => {
if(err)
res.json({error: err})
})
.then(data => {
res.json({data: data})
})
})
// TODO: PUT /albums/:id
app.put('/albums/:id', (req,res) => {
Album.findByIdAndUpdate(req.params.id, req.body, {new: true},
(err, album) =>{
if(err) return res.status(500).send(err)
return res.json({data: album})
})
})
// TODO: DELETE /albums/:id
app.delete('/albums/:id', (req,res) => {
const id = req.params.id
Album.findById(id)
.then(docs => {
docs.remove()
res.status(204)
.json({data:docs})
})
})
// TODO: POST /purchases
app.post('/purchases', (req,res) => {
})```
This might help you. Look into mongoose's populate method.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.findById(purchase.id).populate('user').populate('album').then((purchaseData) => {
return res.json({purchaseData});
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e);
});
})
Here's an alternative for populating after saving the document.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.populate(purchase, [{path: 'user'}, {path: 'album'}], (err, data) => {
if(err) {
return res.json(e);
}
return res.json(data);
});
}).catch(e => {
console.log(e);
});
}
)
As mentioned here: https://mongoosejs.com/docs/api.html#model_Model.populate
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); ?