将 $facet 结果与子文档合并,然后有条件地排除文档

Combine $facet result with subdocument and then conditionally excluding document

假设在 $facet 阶段之后我有一个包含两个数组的结果:roomInfohotelInfo.

看起来像这样:

{
  "roomInfo": [
    {
      _id: 'ab1',
      booked: 3
    },
    {
      _id: 'ab2',
      booked: 1
    }
  ],
  "hotelInfo": [
    {
      name: 'Radison Blue',
      roomDetails: [
        {
          _id: 'ab1',
          roomCount: 5
        },
        {
          _id: 'xy1',
          roomCount: 5
        }
      ]
    },
    {
      name: 'Intercontinental',
      roomDetails: [
        {
          _id: 'ab2',
          roomCount: 5
        }
      ]
    }
  ]
};

预期结果

我想要这样的输出:

[
  {
    name: 'Radison Blue',
    roomDetails: [
      {
        _id: 'ab1',
        roomCount: 5,
        booked: 3
      },
      {
        _id: 'xy1',
        roomCount: 5,
        booked: 0
      }
    ]
  },
  {
    name: 'Intercontinental',
    roomDetails: [
      {
        _id: 'ab2',
        roomCount: 5,
        booked: 1
      }
    ]
  }
];

基本上,将 roomInfo 中的 booked 属性 添加到 hotelInfo匹配他们的 ID 后的 roomDetails 字段。

  1. 此外,在得到上面的输出结果后,我想排除那些所有房间(不是单个房间)都具有字段值 roomCount预订 相等。我想在聚合管道阶段执行此操作,因为稍后我将不得不处理 $skip 和 $limit。

如何实现这些用例?

谢谢!

基本上,该方法将遍历酒店并相应地匹配每个房间,这是一个快速工作的代码示例:

db.collection.aggregate([
  {
    $unwind: "$hotelInfo"
  },
  {
    $project: {
      name: "$hotelInfo.name",
      "roomDetails": {
        $filter: {
          input: {
            $map: {
              input: "$hotelInfo.roomDetails",
              as: "info",
              in: {
                "$mergeObjects": [
                  "$$info",
                  {
                    "$arrayElemAt": [
                      {
                        $filter: {
                          input: "$roomInfo",
                          as: "room",
                          cond: {
                            $eq: [
                              "$$room._id",
                              "$$info._id"
                            ]
                          }
                        }
                      },
                      0
                    ]
                  }
                ]
              }
            }
          },
          as: "proccessedInfo",
          cond: {
            $ne: [
              "$$proccessedInfo.roomCount",
              "$$proccessedInfo.booked"
            ]
          }
        }
      }
    }
  }
])

Mongo Playground

话虽如此,您提到您希望将来对电话进行分页。当前的方法似乎无法扩展,因为这些是“真实数据点”,也就是酒店如果您的规模有一定的上限(不超过数千家酒店),那也没关系。但如果不是,我建议你再问一个关于你的整个管道的问题,这样我们就可以调整它以更好地工作。