how to retrieve data from MongoDB database in node js? - node.js

In node.js I am getting only partial data back.In the second object some data are missing.
The response:
{
'62d12069cb03235286511d5e': [
{
duration: [Object],
isBookingCancelled: [Object],
_id: new ObjectId("62d55611f4a5817f6b0441c6"),
parkingId: new ObjectId("62d12069cb03235286511d5e"),
user: new ObjectId("62c9511cc96c2b690028be91"),
date: 2022-07-22T00:00:00.000Z,
startTime: 2022-07-22T06:30:00.000Z,
endTime: 2022-07-22T08:30:00.000Z,
isFeePaid: false,
status: 'sent',
isStarted: false,
isEnabled: false,
createdAt: 2022-07-18T12:46:09.040Z,
updatedAt: 2022-07-18T12:46:09.040Z,
__v: 0
},
{
duration: [Object],
isEnabled: false,
createdAt: 2022-07-18T12:49:49.921Z,
updatedAt: 2022-07-18T12:49:49.921Z,
__v: 0
}
]
}
Sometime it gives full data but sometime it retrieves only partial data like above. Here is the query.
const bookings = await Booking.find({
"isBookingCancelled.value": false,
// parkingId: { $in: parkingIds },
});
let groupBookings = {};
let tmppid = "";
bookings.forEach((booking) => {
tmppid = booking.parkingId.toString();
if (typeof groupBookings[tmppid] === "undefined")
groupBookings[tmppid] = [];
groupBookings[tmppid].push(booking);
});
console.log(groupBookings);
Booking schema;
ParkingId: ref: Parking, user: referenced to auth, date, startTime, duration: {days, hours, minutes}, endTime, isBookingcancelled, isFeePaid, isSatrted, isEnabled, paymentId refernced to Payment, and status

Related

Filter data in Node.js

I want to subtract already booked data from totalSpots variable whenever this condition returns true
if(totalSpots > bookings.count()){
return true
}
return false
And when it return true I want to store it into a variable called filteredData.
GET route to fetch parking availability:
exports.getParkingListByCriteria = async (req, res) => {
try {
endTime = getEndTime(req.body.startTime, req.body.duration);
let parkings = await Parking.find(
{
"location.city": req.body.city,
}
);
let parkingList = [];
let parkingIds = [];
parkings.forEach((parking) => {
isParkingAvailable(parking.availability, req.body.startTime, endTime);
{
parkingList.push(parking);
parkingIds.push(parking._id);
}
});
const bookings = await Booking.find({
"isBookingCancelled.value": false,
parkingId: { $in: parkingIds },
});
let groupBookings = {};
let tmppid = "";
bookings.forEach((booking) => {
tmppid = booking.parkingId.toString();
if (typeof groupBookings[tmppid] === "undefined")
groupBookings[tmppid] = [];
groupBookings[tmppid].push(booking);
});
var keys = Object.keys(groupBookings);
console.log("parkingList -> ", parkingList);
parkingList.filter((booking) => {
isParkingSlotAvailable(groupBookings, Object.keys(groupBookings));
}); //Stuck in the function
res.status(200).send(parkingList);
} catch (error) {
return res.status(500).json({ error: error.message });
}
};
isParkingSlotAvailable Function:
exports.isParkingSlotAvailable = (groupBookings, keys) => {
groupBookings.forEach((booking) => {});
};
The sample data from console.log(parkingList)
parkingList -> [
{
contactInfo: { name: 'Claudia Shields', phoneNumber: 8904672101 },
location: {
address: '737 applegate court',
city: 'bowie',
state: 'rhode island',
country: 'greece',
zipCode: 10825
},
coordinates: { lng: 34.048954, lat: 10.299556 },
_id: new ObjectId("62d12053cb03235286511d54"),
merchantId: new ObjectId("62c950dfc96c2b690028be88"),
price: 16,
parkingType: 'residence',
parkingInfo: [ [Object] ],
totalSpots: [ 127 ],
status: 'active',
isFeePaid: false,
parkingZone: [],
availability: [ [Object], [Object], [Object], [Object], [Object], [Object] ],
specialEvents: [],
createdAt: 2022-07-15T08:07:47.997Z,
updatedAt: 2022-07-15T09:29:58.696Z,
__v: 0
},
]
The sample data from console.log(groupBookings)
groupBookings: {
'62d12053cb03235286511d54': [
{
duration: [Object],
isBookingCancelled: [Object],
_id: new ObjectId("62d2a9d1cf93195bef1923af"),
parkingId: new ObjectId("62d12053cb03235286511d54"),
user: new ObjectId("62c95116c96c2b690028be8e"),
date: 2022-07-22T00:00:00.000Z,
startTime: 2022-07-22T05:30:00.000Z,
endTime: 2022-07-22T08:40:00.000Z,
isFeePaid: false,
status: 'sent',
isStarted: false,
isEnabled: false,
createdAt: 2022-07-16T12:06:42.002Z,
updatedAt: 2022-07-16T12:15:08.578Z,
__v: 0
},
{
duration: [Object],
isBookingCancelled: [Object],
_id: new ObjectId("62d553f80e8fa13f1295514c"),
parkingId: new ObjectId("62d12053cb03235286511d54"),
user: new ObjectId("62c95136c96c2b690028be9a"),
date: 2022-07-22T00:00:00.000Z,
startTime: 2022-07-22T10:30:00.000Z,
endTime: 2022-07-22T12:30:00.000Z,
isFeePaid: false,
status: 'sent',
isStarted: false,
isEnabled: false,
createdAt: 2022-07-18T12:37:12.682Z,
updatedAt: 2022-07-18T12:37:12.682Z,
__v: 0
}
]
}
Try to change your filter function like this.
Also, make sure that you update the parkingList since filter does not edit the array in-place.
parkingList = parkingList.filter((booking) => {
const booked = groupBookings[booking._id];
const alreadyBooked = booked ? booked.length : 0;
return booking.totalSpots[0] > alreadyBooked;
});

Result of sequelize findByPk

I want to find an itme with the id is: 1
const student = await this.db.Student.findByPk(1)
when I get the result then console it(console.log(student))
student {
dataValues: { id: 1, name: 'Darush', family: 'Hamidi' },
_previousDataValues: { id: 1, name: 'Darush', family: 'Hamidi' },
_changed: Set(0) {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [ 'id', 'name', 'family' ]
},
isNewRecord: false
}
then send the student to browser result will be (res.send(student))?
{
"id": 1,
"name": "Darush",
"family": "Hamidi"
}
why we have a difference ?
I set rwa to true: It works Perfectly
const student = await this.db.Student.findByPk(1,{ raw: true })
The difference appears because using findByPk method (and all similar ones) you get a Sequelize model's instance and not a plain object and when you pass this model instance to res.send it is serialized into plain object with model attributes only.
If you wish to get a plain object from a model instance call get({ plain: true }) and then there will be no difference.
const plainStudentObj = student.get({ plain: true })
res.send(plainStudentObj)

Returns only 1 find document but I request 3 ids to find node/express

Why and how am I saving only document from find query when I pass 3 ids?
I wanted to get from that loop what will return
router.post("/addBand", async (req, res) => {
let singers = req.body.singer
let singerArr = singers.split(', ')
let singer
for (let i = 0; i < singerArr.length; i++) {
// solo = await GroupBand.findOne({ singer: ObjectId(singerArr[i]) }).populate('singer')
singer = await Singer.find({ _id: ObjectId(singerArr[i]) })
console.log(1, singer);
}
console.log(2, singer);
const addedGroup = new GroupBand({
bandName: req.body.bandName,
singer: singer, // [...singer],
debutDate: Date.parse(req.body.debutDate)
})
console.log(3, addedGroup);
return
But it seems like the only one get is from the last id I request. I also tried the spread operator incase it might need to just spread its value, but I get singer is not iterable
1 [ { createdAt: 2019-11-16T05:43:43.971Z,
updatedAt: null,
deletedAt: null,
assignedAt: null,
_id: 5dcf8c8fef739a6159938ca8,
name: 'KyuHyun',
__v: 0 } ]
1 [ { createdAt: 2019-11-16T05:48:51.194Z,
updatedAt: null,
deletedAt: null,
assignedAt: null,
_id: 5dcf8dc320742961c8b5a801,
name: 'Yesung',
__v: 0 } ]
1 [ { createdAt: 2019-11-16T05:53:14.469Z,
updatedAt: null,
deletedAt: null,
assignedAt: null,
_id: 5dcf8eca20742961c8b5a808,
name: 'Ryewook',
__v: 0 } ]
2 { createdAt: 2019-11-16T05:53:14.469Z,
updatedAt: null,
deletedAt: null,
assignedAt: null,
_id: 5dcf8eca20742961c8b5a808,
name: 'Ryewook',
__v: 0 }
3 { createdAt: null,
updatedAt: null,
deletedAt: null,
assignedAt: null,
_id: 5dda2fb9e69e6c22d429bbd9,
bandName: 'Super Junior - K.R.Y',
singer:
[ { createdAt: 2019-11-16T05:53:14.469Z,
updatedAt: null,
deletedAt: null,
assignedAt: null,
_id: 5dcf8eca20742961c8b5a808,
name: 'Ryewook',
__v: 0 } ],
debutDate: 2006-11-04T16:00:00.000Z }
Try this
let singerArr = singers.split(', ')
let singerArrayId=singerArr.map(ele=>ObjectId(ele)) or // let singerArrayId=singerArr.map(ele=>mongoose.Types.ObjectId(ele))
let data=await Singer.find({'_id': { $in:singerArrayId }});
After I got the result from split I loop them to pass on Singer document and find their ids
You should use the &in operator to retrieve more than one documents from your db.
There is an example of use here
EDIT
Try this without the for loop :
singer = await Singer.find({ _id : $in: singerArr }})
This should do the trick as $in operator take an array of ids as argument.

How to get data in sequelize using Noje js

This is code i have used, fetched the all data in database, but i have not getting in value. I'm new for sequelize.
Project.findAll({ raw: true}).then(function (users) {
console.log(users);
console.log(users.dataValues);
}).catch(function (err) {
console.log('Oops! something went wrong, : ', err);
});
This is Output:
This is console.log(users);
[ DAO {
dataValues:
{ idProject: 1,
projectName: 'Symfony',
isActive: '1',
createdAt: 2018-10-23T06:32:43.000Z,
modifiedAt: 2018-10-23T06:32:43.000Z },
_previousDataValues:
{ idProject: 1,
projectName: 'Symfony',
isActive: '1',
createdAt: 2018-10-23T06:32:43.000Z,
modifiedAt: 2018-10-23T06:32:43.000Z },
options: { isNewRecord: false, isDirty: false, raw: true },
hasPrimaryKeys: true,
selectedValues:
RowDataPacket {
idProject: 1,
projectName: 'Symfony',
isActive: '1',
createdAt: 2018-10-23T06:32:43.000Z,
modifiedAt: 2018-10-23T06:32:43.000Z },
__eagerlyLoadedAssociations: [],
isNewRecord: false }.....
This is console.log(users.dataValues);
undefined
How is it possible?
When you use findAll, it returns an array, as you can see here in the documentation:
http://docs.sequelizejs.com/class/lib/model.js~Model.html#static-method-findAll
so you should iterate over this array, like so:
Project.findAll({ raw: true})
.then(projects => {
projects.forEach(project => {
console.log(project);
console.log('project name', project.projectName);
})
}).catch(function (err) {
console.log('Oops! something went wrong: ', err);
});
Optionally you could use Async/Await for a cleaner code:
try {
const projects = await Project.findAll({ raw: true});
projects.forEach(project => {
console.log('project name ', project.projectName);
})
} catch(err) {
console.log('Oops! something went wrong: ', err);
}

Object.assign() creates wierd properties when assigns mongoose doc

MessageThread.findById(req.body._id)
.populate({ path: "messages" })
.exec((err, foundMessageThread) => {
var filtered = foundMessageThread.messages.map(message=>{
return Object.assign({}, message, {isRead: true});
})
console.log("filtered", filtered);
});
console.log shows:
{ '$__':
InternalCache {
strictMode: true,
selected: {},
shardval: undefined,
saveError: undefined,
validationError: undefined,
adhocPaths: undefined,
removing: undefined,
inserting: undefined,
version: undefined,
getters: {},
_id: 5a4c7f2d8b49fc260c396f55,
populate: undefined,
populated: undefined,
wasPopulated: true,
scope: undefined,
activePaths: [Object],
pathsToScopes: {},
ownerDocument: undefined,
fullPath: undefined,
emitter: [Object],
'$options': true },
isNew: false,
errors: undefined,
_doc:
{ sentAt: 2018-01-03T06:58:53.188Z,
isRead: false,
_id: 5a4c7f2d8b49fc260c396f55,
sender: 5a4b77767251b44cd870219f,
reciever: 5a4b780a7251b44cd87021a1,
text: 'qwe',
__v: 0 },
'$init': true,
isRead: true },
......
it repeats many times.
I suppose it (InternalCache { strictMode: true...) relates to message that is taken from foundMessageThread. And it reveals its metadata(in my term) while assigning. Because:
MessageThread.findById(req.body._id)
.populate({ path: "messages" })
.exec((err, foundMessageThread) => {
var filtered = foundMessageThread.messages.map(message=>{
console.log("message", message)
return Object.assign({}, message, {isRead: true});
})
console.log("filtered", filtered);
});
console.log shows
{ sentAt: 2018-01-03T06:58:53.188Z,
isRead: false,
_id: 5a4c7f2d8b49fc260c396f55,
sender: 5a4b77767251b44cd870219f,
reciever: 5a4b780a7251b44cd87021a1,
text: 'qwe',
__v: 0 },
....
My question:
Is it normal behavior?
If it is how to fix it? Because "metadata" prevents objects being assigned.
P.S. I've tried:
MessageThread.findById(req.body._id)
.populate({ path: "messages" })
.exec((err, foundMessageThread) => {
var filtered = foundMessageThread.messages.map(message=>{
return **Object.assign({}, message._doc, {isRead: true})**;
})
console.log("filtered", filtered);
});
This is a normal behaviour with mongoose. Objects returned by mongoose wrap the actual data, so as to add behaviours (methods) to it.
You can get to the actual data object by using toObject method, for eg, message.toObject().
However there are properties like __v, which are used by mongoose for house keeping purposes. If you don't want them, you can modify the toObject method like this
messageSchema.set('toObject', {
versionKey: false,
transform: (doc, ret) => {
delete ret.__v;
return ret;
},
});
You can also use .lean() method with mongoose request. This allows to get less cumbersome response and process it easyly:
try {
const assets = await myModel.Assets
.find({ isActive: true }, { __v: 0, _id: 0 })
.lean()
.exec()
// do something
}
catch(error) {
throw error
}
It appears that the _doc property of mongoose objects should be referenced if you want to either assign to or from those objects. In fact, I was unable to set additional properties in a normal manner like so mongoDoc.newProp = propValue;. It was not altering the original object.
For assignment, instead of:
Object.assign(mongoDoc, {a: 1, b: 2});
You'd want:
Object.assign(mongoDoc._doc, {a: 1, b: 2});
Or if you're assigning the mongoDoc properties to another object, you'd want
Object.assign({a: 1, b: 2}, mongoDoc._doc);
// add .lean() in your query like below
const documents = await DocumentModel.find().lean();
// at debug now ,
// now you will get your result;

Resources