查询文档,其条件基于细分



我有一个 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.datereq.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 }
        ]
    }]
}

最新更新