I have a room schema like this:
let roomSchema = new mongoose.Schema({
events: [{type: mongoose.Schema.ObjectId, ref: 'Event'}],
name: { type: String, required: true, index: { unique: true } }
});
It contains an array of event ids. Event schema:
let eventSchema = new mongoose.Schema({
title: { type: String, required: true },
room: { type: mongoose.Schema.ObjectId, ref: 'Room', required: true },
date: { type: Date, required: true },
slot: { type: Number, required: true }
});
What I am trying to do, is:
"query all rooms, that don't contain events of a particular date AND slot".
So if the date from the request matches the date of a room AND the slot, then that room should not be in the response. If only one of the fields match it should be in the response.
I found similar questions here, but none for my scenario:
https://stackoverflow.com/a/36371665/5115768
Mongoose query where value is not null
I tried something like:
this.model.find(req.query).populate({
path: 'events',
match: {
date: { $ne: req.query.date },
slot: { $ne: req.query.slot }
}
}).exec((err, rooms) => {
rooms = rooms.filter((room) => {
return room.events != null;
});
res.status(200).json(rooms);
});
But of course it doesn't work (rooms is always empty array). I have a really hard time figure this out.
How can I query documents (rooms) with conditions which are based on subdocuments (events)?
UPDATE
I changed my schema and code so that slot
is not an array anymore.
If I understood @Veeram's solution correctly, it can't be used, because it would return empty events
arrays for "reserved rooms". The problem with this is that I need to filter out these rooms with empty events
array, which would include rooms that didn't have any events associated in the first place (these shouldn't be filtered out).
Now I managed to get all "reserved rooms" (the ones that contain an event that matches req.query.date
AND req.query.slot
):
this.model.find(req.query).populate({
path: 'events',
match: {
$and: [
{ date: { $eq: date } },
{ slot: { $eq: slot } }
]
}
}).exec((err, reservedRooms) => {
reservedRooms = reservedRooms.filter(room => room.events.length > 0);
res.status(200).json(reservedRooms);
});
This is the exact opposite of what I want but it's a start, how can I "reverse" that?