Reputation: 1
I'm creating a CRUD app in NodeJS and Express to teach myself backend programming. On the database side I use mongodb. This project is basically a sort of shop back office (currently no frontend) where you could add, update delete or look at an ITEM. (To mention it, use POSTMAN as the request handler).
Problem description : The update method currently works so i can update an ITEM based on its ID but if I miss a field then the value given to this field is 'null' which is logical. But What I want is to be able to update whatever field or properties of my ITEM and get the default db value for the field I don't update.
As an information in the ITEM Model i've got : - price - name - brand - desc - category - _id
A friend of mine explained me that I had to use Async/await because i had to first retrieve the value for the specific field I don't want to update necessarily and then handled the case where this value is not updated by indicating this retrieved value instead.
I tried that but i'm a bit confused with the way I should use the async/ await and so i can't get it to work.
const update = (req, res) => {
const { id } = req.params
const { price, name, brand, description, category } = req.body
const currCat = await Item.findById(id, (err, item) => err ? res.send(err) : res.send(item.category))
//console.log(currCat)
Item
//attempt to get default category value - .findById(id, (err, item) => err ? res.send(err) : res.send(item.category)
.findByIdAndUpdate(id, { price, name, brand, description, category }, {new: true})
.then(item => item ? res.send(item) : res.status(404).send({message: "item not found with id : " + id}))
.then(item => item.category == null ? res.send(currCat) : res.send({message: "the category was specified so np"}))
}
now if comment the currCat declaration line and the last .then line the thing work as before, which is updating everything is possible but if one or another field is not in the JSON post request body it puts "null" value.
here's the JSON POST request:
{
"price": 34,
"name": "I just changed your name",
"brand": "5d57fa1eaf168b29a4b1c00b",
"description": "I changed the value again"
}
and here's what's printed :
{
"_id": "5d631112e2fc2d39f21c334b",
"price": 34,
"name": "I just changed your name",
"brand": "5d57fa1eaf168b29a4b1c00b",
"description": "I changed the value again",
"category": null,
"__v": 0
}
I'm quite sure it's only solvable with async await but can't get it to work please help me guys ! :)
EDIT :
Here's the result when i use your method, with this request :
Here's the request body where you can see I didn't put the category field as i want to keep the default value which is already in the object
{
"price": 34,
"name": "I just changed your name",
"brand": "5d57fa1eaf168b29a4b1c00b",
"description": "I changed the value again"
}
and here's the result :
(node:11759) UnhandledPromiseRejectionWarning: ValidationError: Item validation failed: category: Path `category` is required.
at new ValidationError (/home/eternano/Documents/JS/InventoryApp/node_modules/mongoose/lib/error/validation.js:30:11)
at model.Document.invalidate (/home/eternano/Documents/JS/InventoryApp/node_modules/mongoose/lib/document.js:2317:32)
at p.doValidate.skipSchemaValidators (/home/eternano/Documents/JS/InventoryApp/node_modules/mongoose/lib/document.js:2166:17)
at /home/eternano/Documents/JS/InventoryApp/node_modules/mongoose/lib/schematype.js:1037:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
(node:11759) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:11759) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
PUT /inventory/update/5d631112e2fc2d39f21c334b - - ms - -
Upvotes: 0
Views: 440
Reputation: 44
So there is no need to use findById and findByIdAndUpdate in the same time. If you want to use findById then you probably update fields manually and you should add async flag to you function and handle errors using http-errors module like this:
const createError = require('http-errors');
const update = async (req, res) => {
const {id} = req.params;
const {price, name, brand, description, category} = req.body;
const item = await Item.findById(id);
if (!item) {
throw createError(404, `Item not found with id ${id}`);
}
item.price = price;
item.name = name;
// and so on for the others...
return item.save();
};
Another approach is to use updateOne() also you can see how it works in the docs of mongoose.
Hope this helps!
Upvotes: 0