Related
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;
});
Chatrooms.findOneAndUpdate({Roomname: room.Roomname},{ $setOnInsert: {status: true, userNum: 1}}, {new: true, upsert: true}, function(err, doc) {
if(err) console.log(err);
console.log("DOC " + doc)
if(doc.status) {
// FOUND ROOM SATTUS IS TRUE LOGIC
console.log(doc);
// return callback(true)
}
});
Above query will return to me the actual document that's updated or inserted but I can't check exactly which one it is. If I do an update instead of findOneandUpdate I'm returned this
{
ok: 1,
nModified: 0,
n: 1,
upserted: [ { index: 0, _id: 55df883dd5c3f7cda6f84c78 } ]
}
How do I return both the document and the write result or at least the upserted field from the write result.
As of 8 August 2019 (Mongoose Version 5.6.9), the property to set is "rawResult" and not "passRawResult":
M.findOneAndUpdate({}, obj, {new: true, upsert: true, rawResult:true}, function(err, d) {
if(err) console.log(err);
console.log(d);
});
Output:
{ lastErrorObject:
{ n: 1,
updatedExisting: false,
upserted: 5d4befa6b44b48c3f2d21c75 },
value: { _id: 5d4befa6b44b48c3f2d21c75, rating: 4, review: 'QQQ' },
ok: 1 }
Notice also the result is returned as the second parameter and not the third parameter of the callback. The document can be retrieved by d.value.
Version 4.1.10 of Mongoose has an option called passRawResult which if set to true causes the raw parameter to be passed. Leaving out this option seems to default to false and cause raw to always be undefined:
passRawResult: if true, passes the raw result from the MongoDB driver
as the third callback parameter
http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate
Alright so my main problem was that I couldn't get the _id of the document I inserted without not being able to check whether if it was updated/found or inserted. However I learned that you can generate your own Id's.
id = mongoose.Types.ObjectId();
Chatrooms.findOneAndUpdate({Roomname: room.Roomname},{ $setOnInsert: {_id: id, status: true, userNum: 1}}, {new: true, upsert: true}, function(err, doc) {
if(err) console.log(err);
if(doc === null) {
// inserted document logic
// _id available for inserted document via id
} else if(doc.status) {
// found document logic
}
});
Update
Mongoose API v4.4.8
passRawResult: if true, passes the raw result from the MongoDB driver as the third callback parameter.
I'm afraid Using FindOneAndUpdate can't do what you whant because it doesn't has middleware and setter and it mention it the docs:
Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:
defaults
Setters
validators
middleware
http://mongoosejs.com/docs/api.html search it in the findOneAndUpdate
if you want to get the docs before update and the docs after update you can do it this way :
Model.findOne({ name: 'borne' }, function (err, doc) {
if (doc){
console.log(doc);//this is ur document before update
doc.name = 'jason borne';
doc.save(callback); // you can use your own callback to get the udpated doc
}
})
hope it helps you
I don't know how this got completely off track, but there as always been a "third" argument response to all .XXupdate() methods, which is basically the raw response from the driver. This always tells you whether the document is "upserted" or not:
Chatrooms.findOneAndUpdate(
{ "Roomname": room.Roomname },
{ "$setOnInsert": {
"status": true, "userNum": 1
}},
{ "new": true, "upsert": true },
function(err, doc,raw) {
if(err) console.log(err);
// Check if upserted
if ( raw.lasErrorObject.n == 1 && !raw.lastErrorObject.updatedExisting ) {
console.log("upserted: %s", raw.lastErrorObject.upserted);
}
console.log("DOC " + doc)
if (doc.status) {
// FOUND ROOM SATTUS IS TRUE LOGIC
console.log(doc);
// return callback(true)
}
});
Which will tell you the _id of the document that was just upserted.
From something like this in the "raw" response:
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e12c65f6044f57c8e09a46 },
value: { _id: 55e12c65f6044f57c8e09a46,
status: true,
userNum: 1
__v: 0 },
ok: 1 }
Complete reproducible listing:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var testSchema = new Schema({
name: String
});
var Test = mongoose.model('Test', testSchema, 'test');
async.series(
[
function(callback) {
Test.remove({},callback);
},
function(callback) {
async.eachSeries(
["first","second"],
function(it,callback) {
console.log(it);
Test.findOneAndUpdate(
{ "name": "Bill" },
{ "$set": { "name": "Bill" } },
{ "new": true, "upsert": true },
function(err,doc,raw) {
console.log(raw),
console.log(doc),
callback(err);
}
);
},
callback
);
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
Which outputs:
first
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e2a92328f7d03a06a2dd6b },
value: { _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 },
ok: 1 }
{ _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 }
second
{ lastErrorObject: { updatedExisting: true, n: 1 },
value: { _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 },
ok: 1 }
{ _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 }
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;
Chatrooms.findOneAndUpdate({Roomname: room.Roomname},{ $setOnInsert: {status: true, userNum: 1}}, {new: true, upsert: true}, function(err, doc) {
if(err) console.log(err);
console.log("DOC " + doc)
if(doc.status) {
// FOUND ROOM SATTUS IS TRUE LOGIC
console.log(doc);
// return callback(true)
}
});
Above query will return to me the actual document that's updated or inserted but I can't check exactly which one it is. If I do an update instead of findOneandUpdate I'm returned this
{
ok: 1,
nModified: 0,
n: 1,
upserted: [ { index: 0, _id: 55df883dd5c3f7cda6f84c78 } ]
}
How do I return both the document and the write result or at least the upserted field from the write result.
As of 8 August 2019 (Mongoose Version 5.6.9), the property to set is "rawResult" and not "passRawResult":
M.findOneAndUpdate({}, obj, {new: true, upsert: true, rawResult:true}, function(err, d) {
if(err) console.log(err);
console.log(d);
});
Output:
{ lastErrorObject:
{ n: 1,
updatedExisting: false,
upserted: 5d4befa6b44b48c3f2d21c75 },
value: { _id: 5d4befa6b44b48c3f2d21c75, rating: 4, review: 'QQQ' },
ok: 1 }
Notice also the result is returned as the second parameter and not the third parameter of the callback. The document can be retrieved by d.value.
Version 4.1.10 of Mongoose has an option called passRawResult which if set to true causes the raw parameter to be passed. Leaving out this option seems to default to false and cause raw to always be undefined:
passRawResult: if true, passes the raw result from the MongoDB driver
as the third callback parameter
http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate
Alright so my main problem was that I couldn't get the _id of the document I inserted without not being able to check whether if it was updated/found or inserted. However I learned that you can generate your own Id's.
id = mongoose.Types.ObjectId();
Chatrooms.findOneAndUpdate({Roomname: room.Roomname},{ $setOnInsert: {_id: id, status: true, userNum: 1}}, {new: true, upsert: true}, function(err, doc) {
if(err) console.log(err);
if(doc === null) {
// inserted document logic
// _id available for inserted document via id
} else if(doc.status) {
// found document logic
}
});
Update
Mongoose API v4.4.8
passRawResult: if true, passes the raw result from the MongoDB driver as the third callback parameter.
I'm afraid Using FindOneAndUpdate can't do what you whant because it doesn't has middleware and setter and it mention it the docs:
Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:
defaults
Setters
validators
middleware
http://mongoosejs.com/docs/api.html search it in the findOneAndUpdate
if you want to get the docs before update and the docs after update you can do it this way :
Model.findOne({ name: 'borne' }, function (err, doc) {
if (doc){
console.log(doc);//this is ur document before update
doc.name = 'jason borne';
doc.save(callback); // you can use your own callback to get the udpated doc
}
})
hope it helps you
I don't know how this got completely off track, but there as always been a "third" argument response to all .XXupdate() methods, which is basically the raw response from the driver. This always tells you whether the document is "upserted" or not:
Chatrooms.findOneAndUpdate(
{ "Roomname": room.Roomname },
{ "$setOnInsert": {
"status": true, "userNum": 1
}},
{ "new": true, "upsert": true },
function(err, doc,raw) {
if(err) console.log(err);
// Check if upserted
if ( raw.lasErrorObject.n == 1 && !raw.lastErrorObject.updatedExisting ) {
console.log("upserted: %s", raw.lastErrorObject.upserted);
}
console.log("DOC " + doc)
if (doc.status) {
// FOUND ROOM SATTUS IS TRUE LOGIC
console.log(doc);
// return callback(true)
}
});
Which will tell you the _id of the document that was just upserted.
From something like this in the "raw" response:
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e12c65f6044f57c8e09a46 },
value: { _id: 55e12c65f6044f57c8e09a46,
status: true,
userNum: 1
__v: 0 },
ok: 1 }
Complete reproducible listing:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var testSchema = new Schema({
name: String
});
var Test = mongoose.model('Test', testSchema, 'test');
async.series(
[
function(callback) {
Test.remove({},callback);
},
function(callback) {
async.eachSeries(
["first","second"],
function(it,callback) {
console.log(it);
Test.findOneAndUpdate(
{ "name": "Bill" },
{ "$set": { "name": "Bill" } },
{ "new": true, "upsert": true },
function(err,doc,raw) {
console.log(raw),
console.log(doc),
callback(err);
}
);
},
callback
);
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
Which outputs:
first
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e2a92328f7d03a06a2dd6b },
value: { _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 },
ok: 1 }
{ _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 }
second
{ lastErrorObject: { updatedExisting: true, n: 1 },
value: { _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 },
ok: 1 }
{ _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 }
I like to update an entry in mongodb. But lodash only update one value in the array. I send this object to my node.js server:
{ _id: 5593df7c087e59a00c04cda3,
name: 'blueberry',
uuid: 'b9407f30-f5f8-466e-aff9-25556b57fe6d',
major: '12345',
minor: '12345',
position: 'Kantine',
__v: 18,
messages:
[ { _id: 5593df7c087e59a00c04cda4,
timeRange: [Object],
url: '',
message: 'j',
title: 'jv',
messageType: 'text' },
{ _id: 5593df7c087e59a00c04cda4,
timeRange: [Object],
url: '',
message: 'j',
title: 'jv',
messageType: 'text' } ] }
Here is the code for the update of the mongodb-entry:
// Updates an existing ibeacons in the DB.
exports.update = function(req, res) {
Ibeacons.findById(req.params.id, function (err, ibeacons) {
if (err) { return handleError(res, err); }
if(!ibeacons) { return res.send(404); }
var updated = _.merge(ibeacons, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, ibeacons);
});
});
};
But I get this as result:
{ _id: 5593df7c087e59a00c04cda3,
name: 'blueberry',
uuid: 'b9407f30-f5f8-466e-aff9-25556b57fe6d',
major: '12345',
minor: '12345',
position: 'Kantine',
__v: 18,
messages:
[ { _id: 5593df7c087e59a00c04cda4,
timeRange: [Object],
url: '',
message: 'j',
title: 'jv',
messageType: 'text' },
{ _id: 5593df7c087e59a00c04cda4,
timeRange: [Object],
url: '',
message: 'j',
title: 'jv',
messageType: 'text' } ] }
Maybe someone can help me.
Ok I get it. the version of lodash was on 2.4.1 now I updated it to 3.1.0 and it works. :D