NOT WORKING: Mongoose findByIdAndUpdate() does not work - node.js

I am trying to create a (MERN stack) management system that keeps track of vacant rooms in a hotel.
I am trying to change the roomTypeAOccupiedTotal from 2 to 3.
From the client side, it sends an axios.put()request as follows:
axios
.put(`http://localhost:8082/api/myHotel/${branchStatus.id}`, data)
this is the server-side code:
router.put('/:_id', (req, res) => {
/*
req.params looks like this:
{ _id: '63b4d533fabbf31cdb519896' }
req.body looks like this:
roomOccupied5F: 3,
roomOccupied6F: 5,
roomTypeAOccupiedTotal: 2,
roomTypeBOccupiedTotal: 8,
*/
let filter = { _id: mongoose.Types.ObjectId(req.params._id) }
let update = { $set: req.body }
MyHotel.findByIdAndUpdate(filter, update, {new: true})
.then(data => res.json({ msg: 'updated successfully' }))
.catch(err =>
res.status(400).json({ error: 'Unable to update the Database' })
);
Below are the GET request and PUT request sent using POSTMAN.
after the message "updated successfully", I sent another GET request to check, but there are no changes to the variable(roomTypeAOccupiedTotal).
Could someone help me with solving this problem? the findByIdAndUpdate() method is working, as its not throwing any errors, but its not updating.

I believe your problem is the filter object. Looking at the docs for findByIdAndUpdate, it expects to receive the id param, not a filter object.
https://mongoosejs.com/docs/api/model.html#model_Model-findByIdAndUpdate
Parameters:
id «Object|Number|String» value of _id to query by
Additionally, when you create an objectId out of the request param, you aren't creating a new instance of it, so whatever was passed in would have failed to match anything. My IDE highlights this for me:
Your fix is likely something like this:
const id = new mongoose.Types.ObjectId(req.params._id)
MyHotel.findByIdAndUpdate(id, update, {new: true})

No need to convert id, and no need to use the update operator(i.e. $set).
try this:
MyHotel.findByIdAndUpdate(req.params._id, req.body, { new: true }, (err, hotel) => {
if (err) {
console.log(err);
} else {
console.log(hotel);
}
});

Related

How to update document in MongoDB through Mongoose

I am trying to update my document field with the following code, but I catch an error "Cannot GET /updation".
My code:
router.put('/updation', (req, res) => {
const query = { email: "babra#arzepak.com" };
const newEmail = { $set: { name: "babra", email: "nadralatif952#gmail.com" } };
Registration.updateOne()
.then((registration) => {
console.log("updating");
res.render('index', { title: 'updating registrations', registrations });
})
.catch(() => {
res.send('Sorry! Something went wrong.');
});
});
send a request with PUT method and you didn't use of query and newEmail as arguments for updateOne() pass them, and in new version of mongoose you don't need to $set for updating so change your code like this :
router.put('/updation', (req, res) => {
const query = { email: "babra#arzepak.com" }
const newEmail = { name: "babra", email: "nadralatif952#gmail.com" }
Registration.updateOne(query,newEmail)
.then((registration) => {
console.log("updating")
res.render('index', { title: 'updating registrations', registrations });
})
.catch(() => { res.send('Sorry! Something went wrong.'); });
})
Wrong Method
In your router you registered a route '/updation' for PUT method.
Hence only request with method PUT will be handled by your router. The error Cannot GET /updation means you are trying to handle a request with GET method which is simply not registered by your router.
A - If this code is supposed to get triggered when you visit the page via browser, then you should register the route for GET method, like router.get('/updation', ... ),
or
B - If this code is supposed to run seperate from your view (like a REST API should), then use a PUT request and end the request inside your router with res.status(200).json(yourdata)
📑 Sidenote :
It looks like you did not completely setup your mongoose query, I mean you defined the query but you don't use it in the database request. To use the defined query you propbably should change your code, according to the mongoose docs : https://mongoosejs.com/docs/api/model.html#model_Model.updateOne . I am not including a specific code example here, since it's not part of the question.

MongoDB CRUD routes returning null or wrong values

I've recently started using the MEAN stack and stumbled upon some errors while trying to work with my MongoDB database. I connected to the database successfully, implemented my CRUD routes, and I get wrong values for anything besides the find() method (which returns all the documents in my collection without any problem). The findOne() looks like this for example:
router.route(server.get("/company/:id", (request, response) => {
const companyId = request.params.id;
console.log("Showing company with id: " + companyId)
dbCollection.findOne({ _id: mongodb.ObjectId(companyId) }, (error, result) => {
if (error) throw error;
// return company
response.json(result);
});
}));
The result after making a get request via Postman is null
The insertOne() looks like this:
router.route(server.post("/company/add", (request, response) => {
const company = request.body;
dbCollection.insertOne(company, (error, result) => {
if (error) throw error;
// return updated list
dbCollection.find().toArray((_error, _result) => {
if (_error) throw _error;
response.json(_result);
});
});
}));
It adds one document to the database with the ID that it creates for itself, but for some reason it doesn't take in the body data (2 string elements { "name": "xy", "type": "company" })
And last but not least, the deleteOne():
router.route(server.delete("/company/delete/:id", (req, res) => {
const companyId = req.param.id;
console.log("Delete company with id: ", companyId);
dbCollection.deleteOne({ _id: mongodb.ObjectId(companyId) }, function(err, result) {
if (err) throw err;
// send back entire updated list after successful request (optional)
dbCollection.find().toArray(function(_err, _result) {
if (_err) throw _err;
res.json(_result);
});
});
}));
For some reason it deletes the very first document in the collection, but not the one that is entered with the corresponding ID.
If anyone could help me out with this it would be awesome. Thank you in advance!
Edit 1:
Adding a new document to the collection via Postman
Collection after the add
Edit 2:
Get request via ID and response (returns null)
Console output:
Showing company with id: 5e63db861dd0ce2418ce423d
Edit 3:
Corrected the code for the findOne() and deleteOne() methods.
When you try with _id you need to convert the string(request.params.id) to ObjectId().
Convert string to ObjectID in MongoDB - whoami

Sequelize - Creating Multiple Tables Using Id of First Table Created

I'm doing a project using Express, & Sequelize and have run into an issue:
I'm trying to create an api route that, on a button click, will create a row in my 'member' & 'memberinstrument' tables. Those tables have an association in my models that: member 'hasMany' memberinstruments & memberinstruments 'belongsTo' member.
This is what I have right now:
router.post("/api/individual/signup", async (req, res) => {
try {
const member = await db.Member.create({
memberName: req.body.memberName,
location: `${req.body.city}, ${req.body.state}`,
profilePicture: req.body.profilePicture,
UserId: req.user.id
})
const memberInstrument = await db.MemberInstrument.create({
instrument: req.body.instrument,
MemberId: member.id
});
res.json({ member, memberInstrument });
} catch (error) {
console.log(error.message);
res.status(500).send('Sever Error');
}
})
I'm testing it out in postman and it simply says I have a 'server error' (which doesn't happen if I delete the whole memberInstrument posting section) and in node I get "Cannot read property 'id' of undefined". I know it must have something to do with the timing of trying to create member, and then trying to get that member id for memberinstrument, but I can't figure out how to resolve this.
Any help would be much appreciated!
(edit:
I commented out both UserId & MemberId and it successfully posts.
uncommenting just UserId creates the same error:
UserId is a nullable field so I don't know why it's doing a server error if I don't define it (or maybe I have to define it as null but I do not know how to do that in postman since it's coming from .user instead of .body
uncommenting just MemberId creates the same error)
Since I'm doing this in Postman, and don't know how to send a req.body with that, I was getting that id error. I changed req.user.id to req.body.id which will be populated with information from a front end state and it is now working correctly.
I think it's unnecessary for you to include all the fields in your .create()
try this
router.post("/api/individual/signup", async (req, res) => {
try {
const data = req.body;
const member = await db.Member.create(data);
const [registration, created] = member;
if(created){
//insert more of your code here on creating **MemberInstrument**, this is just a sample.
await db.MemberInstrument.create(registration.member_id);
}
res.json({
registration,
created
});
} catch (error) {
console.log(error);
res.status(500);
}
}
On your postman request, you will input the body or fields in json format, except the ID, IDs should not be included on the postman body.

Posting multiple documents using postman not working

I'm trying to post data using postman, but when I tried to use multiple documents, it shows blank in my mongodb. But when I try to insert a single document, it saves the data. Please correct me, I'm new to this
server.js
app.post('/bloodinventory', function(req, res) {
var bloodinventory= new Bloodinventories();
bloodinventory.blood_group = req.body.blood_group;
bloodinventory.blood_category = req.body.blood_category;
bloodinventory.num_stock = req.body.num_stock;
bloodinventory.save(function(err) {
if (err) {
res.json({ success: false, message: 'Blood Donation already exists!' });
} else {
res.json({ success: true, message: 'Blood Donation Created!' });
}
});
});
Then in my postman, I tried to insert this data:
{
"bloodinventories":[
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
},
{
"blood_group":"A_negative",
"blood_category":"platelet",
"num_stock":9
}
]
}
Then nothing shows in my mongodb, result:
_id:5c45c6a495788ec2c47f8c8b
__v:0
When you provide single document in your POST request
Example:-
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
}
it easly get request.body.blood_group, request.body.blood_category and show on
But when you pass Mutliple document in POST request in array form
{
"bloodinventories":[
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
},
{
"blood_group":"A_negative",
"blood_category":"platelet",
"num_stock":9
}
]
}
Now your request is getting a array so your request body contain bloodinventories. And you can access it as request.body.bloodinventories
Take this const and apply loop on it and insert all document.
Or Simply make API like this and always send array in every request of insert.
Bloodinventories.insertMany(request.body.bloodinventories).then((result) => {
//Success Message
}).catch(err => {
// Error Message
});
It May Help For You...

How to update some data based on array value in Mongoose?

I'd like to update some data in Mongoose by using array value that I've find before.
Company.findById(id_company,function(err, company) {
if(err){
console.log(err);
return res.status(500).send({message: "Error, check the console. (Update Company)"});
}
const Students = company.students;
User.find({'_id':{"$in" : Students}},function(err, users) {
console.log(Students);
// WANTED QUERY : Update company = null from Users where _id = Students[];
});
});
Students returns users._id in array with object inside, and I use that to find users object, and then I want to set null a field inside users object, that field named as "company". How I can do that? Thank you.
From what you posted (I took the liberty to use Promises but you can roughly achieve the same thing with callbacks), you can do something like:
User.find({'_id':{"$in" : Students}})
.then( users =>{
return Promise.all( users.map( user => {
user.company = null;
return user.save()
}) );
})
.then( () => {
console.log("yay");
})
.catch( e => {
console.log("failed");
});
Basically, what I'm doing here is making sure .all() user models returned by the .find() call are saved properly, by checking the Promised value returned for .save()ing each of them.
If one of these fails for some reasons, Promise.all() return a rejection you can catch afterhand.
However, in this case, each item will be mapped to a query to your database which is not good. A better strategy would be to use Model.update(), which will achieve the same, in, intrinsically, less database queries.
User.update({
'_id': {"$in": Students}
}, {
'company': <Whatever you want>
})
.then()
use .update but make sure you pass option {multi: true} something like:
User.update = function (query, {company: null}, {multi: true}, function(err, result ) { ... });

Resources