【问题标题】:Combine $facet result with subdocument and then conditionally excluding document将 $facet 结果与子文档结合,然后有条件地排除文档
【发布时间】:2021-10-04 15:04:11
【问题描述】:

假设在 $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 属性添加到 hotelInforoomDetails 字段中,然后匹配它们的 id .

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

如何实现这些用例?

谢谢!

【问题讨论】:

    标签: mongodb merge mongodb-query aggregation-framework aggregation


    【解决方案1】:

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

    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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      相关资源
      最近更新 更多