How to remove an element from an array included in an Object - node.js

I'm trying to build an application, using MongoDB and nodejs.
I have a model Ride, which contains an array of userID called steps. I'd like to delete one userID entry from a Ride specified by its own RideID.
I have tried the following code, but it's not working, an error is always raised
router.post('/quitRide',async (req,res)=>{
let userID = req.body.userID; //userID to be deleted
let rideID = req.body.rideID; //rideID of the Ride we want to access
Ride.find({_id:rideID})
.exec()
.then(t => {
t[0].steps.splice(t[0].steps.indexOf(userID), 1);
res.status(200);
})
.catch(err => res.status(400).json({error : err}))
})
Here's the error I get :
{error: "erreurTypeError: Cannot read property 'indexOf' of undefined"}
It seems like steps are somehow not accessible

Try using $pull, for more go to this link
router.post('/quitRide',async (req,res)=>{
let userID = req.body.userID; // userID to be deleted
let rideID = req.body.rideID; // rideID of the Ride we want to access
Ride.findOneAndUpdate({_id:rideID}, { $pull: { steps: userId } })
.exec()
.then(t => {
// response with success
res.status(200);
})
.catch(err => res.status(400).json({error : err}))
})

You can use the Lodash Remove function to remove the elements from the array.
you can install the npm package by running this command npm i --save lodash.remove and then do the changes in your code.
router.post('/quitRide',async (req,res)=>{
let userID = req.body.userID; //userID to be deleted
let rideID = req.body.rideID; //rideID of the Ride we want to access
Ride.find({_id:rideID})
.exec()
.then(t => {
_.remove(t[0].steps,userID);
console.log(t[0].steps)//which contains your array without userID
res.status(200);
})
.catch(err => res.status(400).json({error : err}))
})
Don't forget to import/require the lodash package and you can find the documentation on below link
https://lodash.com/docs/4.17.14#remove

Related

NOT WORKING: Mongoose findByIdAndUpdate() does not work

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);
}
});

How to make sure that even if no data is given in the required field, it will consider is empty?

I am using Node.js and MongoDB. I want to make sure that if the user writes in the specific field, the database should be updated with that value, else it should be null.
Following is the code I am using:
exports.updatingUser = async (user_,request,res)=> {
let result = "";
const updateUserInfo = {
fullName: request.fullName,
userName: request.userName,
email :request.email,
password : request.password,
profileImage:request.profileImage,
backgroundImage:request.backgroundImage
};
await User.updateOne({_id:request._id},{$set:updateUserInfo})
.exec()
.then(docs => {
result = docs;
})
.catch(err => {
res.status(500).json({
error: err
});
});
return result;
}
This works when the user writes in the specific fields but not when any of the field is empty.
Try like this
fullName: request.fullName ? request.fullName : '', // You can put null if you want
Note: Need to put in all

How can I lookup which objects in a MongoDB collection contain a field with specific information in it?

I have a web application which allows user to bring up a page, called "Cruise Ship". On that page, I would like users to be able to see other cruise ships from the same cruise line. My MongoDB model for the ships has cruiseLine as a field. This is how I have my view controller structured:
exports.getShip = catchAsync(async (req, res, next) => {
const ship = await Ship.findOne({ slug: req.params.slug }).populate({
path: 'reviews',
fields: 'review rating user displayDate ratingsQuantity',
});
const reviewCount = await Review.count();
const allShips = await Ship.find();
if (!ship) {
return next(new AppError('Page does not exist. Please try again.', 404));
}
res.status(200).render('ship', {
title: `${ship.shipName} Reviews`,
ship,
allShips,
reviewCount,
});
});
I tried including something like this, but it returns undefined:
const cruiseLineInfo = await Ship.find({ cruiseLine: ship.cruiseLine })
In my attempt, I was hoping that ship.cruiseLine would be interpreted as a the cruise line for the specific ship page (example, "Carnival Cruise Line") and then cruiseLineInfo would contain all of the ship objects that matched the find query. But alas, it has not worked. Any suggestions would be appreciated.
I was able to accomplish this in Pug using inline Javascript, a loop and an "if" statement.
- var thisCruiseLine = ship.cruiseLine
- var thisShipName = ship.shipName
each ship in allShips
if ship.cruiseLine == thisCruiseLine && ship.shipName != thisShipName
p #{ship.shipName}
In Mongoose, .find() only builds a query, but that doesn’t run the query immediately. You could build a query first and then run it some time later.
To execute your query, you can either add a callback as a parameter to .find() or chain an .exec() right behind it:
const cruiseLineInfo = await Ship.find({ cruiseLine: ship.cruiseLine }, (error, response) => {
// do something with the response
})
In your case, the .exec() seems more appropriate:
const cruiseLineInfo = await Ship.find({ cruiseLine: ship.cruiseLine }).exec()

is it possible to add extra field in req.body and add them in a collection using nodejs?

I am trying to store some values in a collection like i got a req.body at the endpoint and i wanted to add timestamp inside the req.body object.
like here is the req.body object
{
name:'xanderous',
city:'Delhi'}
and i want to convert this into this way
{
name:'xanderous',
city:'Delhi',
timestamp:1235456555}
how can i try to solve this issue
const profileStore = async (req, res) => {
try {
// console.log(JSON.stringify(req.body))
await db.collection('Profiles').doc(`${req.body.phoneNumber}`).set(req.body,{merge:true})
console.log('profile')
res.status(200).send({ success: true, message: `Success` })
} catch (error) {
res.status(500).send(error);
}
};
module.exports = {profileStore};
i know i can add the timestamp as an extra field outside the req.body but i have stored the value in the req.body format so i need to store in the given scenario.
const newBody = {
timestamp: Date.now(),
...req.body
}
await db.collection('Profiles').doc(`${req.body.phoneNumber}`).set(newBody,{merge:true})

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.

Resources