我有一个 room 架构:
let roomSchema = new mongoose.Schema({
events: [{type: mongoose.Schema.ObjectId, ref: 'Event'}],
name: { type: String, required: true, index: { unique: true } }
});
它包含事件ID数组。事件架构:
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 }
});
我要做的是:
"查询所有房间,不包含特定 date and slot 的事件。
因此,如果请求的日期与房间和插槽的日期匹配,则该房间不应在响应中。如果只有一个字段匹配,则应该在响应中。
我在这里找到了类似的问题,但没有针对我的情况:
https://stackoverflow.com/a/36371665/5115768
猫绿色查询,值不为null
我尝试了类似的东西:
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);
});
,但是当然不起作用(房间总是空数组)。我很难解决这个问题。
我如何查询基于子插图(事件)的条件的文档(房间)?
更新
我更改了模式和代码,以使slot
不再是数组。
如果我正确理解了 @veeram的解决方案,则无法使用它,因为它会返回"保留房间"的空 events
阵列。问题是我需要用空的events
数组过滤这些房间,其中包括一开始没有任何事件的房间(这些房间不应被过滤掉)。
现在,我设法获得了"保留房间"。(包含与req.query.date
和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);
});
这与我想要的完全相反,但这是一个开始,我如何反向那?
填充物应用于事件数组中的每个事件的匹配条件。
因此,当在事件数组的每个元素上应用否定时,在没有可用事件(无匹配)时,在可用事件(匹配)的数组之间丢失了区别,当您获得填充的数组时。
因此,您必须使用服务器$lookup
在整个数组上应用标准。
以下集合查询将过滤房间,其中事件(如存在时)不包含查询中给出的日期和插槽的文档。
中给出的日期和插槽。使用 $elemMatch
比较同一元素上的查询条件,然后 $not
返回没有数组元素包含查询条件的房间。
this.model.aggregate([
{
"$match":{"events":{"$exist":true}}
},
{
"$lookup": {
"from": "events", // Collection name not model or schema name
"localField": "events",
"foreignField": "_id",
"as": "events"
}
},
{
"$match":{"$not":{"$elemMatch":{"date": date, "slot":slot}}}
}
]).exec((err, reservedRooms) => {});
这将用事件输出房间。您可以通过使用$project
从最终输出中删除事件。添加{$project:{"events":0}}
作为最后阶段。
您是否尝试过:
match: {
$not: [{
$and: [
date: { $eq: req.query.date },
slot: { $in: req.query.slot }
]
}]
}