将 $facet 结果与子文档合并,然后有条件地排除文档
Combine $facet result with subdocument and then conditionally excluding document
假设在 $facet 阶段之后我有一个包含两个数组的结果:roomInfo 和 hotelInfo.
看起来像这样:
{
"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 字段。
- 此外,在得到上面的输出结果后,我想排除那些所有房间(不是单个房间)都具有字段值 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"
]
}
}
}
}
}
])
话虽如此,您提到您希望将来对电话进行分页。当前的方法似乎无法扩展,因为这些是“真实数据点”,也就是酒店如果您的规模有一定的上限(不超过数千家酒店),那也没关系。但如果不是,我建议你再问一个关于你的整个管道的问题,这样我们就可以调整它以更好地工作。
假设在 $facet 阶段之后我有一个包含两个数组的结果:roomInfo 和 hotelInfo.
看起来像这样:
{
"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 字段。
- 此外,在得到上面的输出结果后,我想排除那些所有房间(不是单个房间)都具有字段值 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"
]
}
}
}
}
}
])
话虽如此,您提到您希望将来对电话进行分页。当前的方法似乎无法扩展,因为这些是“真实数据点”,也就是酒店如果您的规模有一定的上限(不超过数千家酒店),那也没关系。但如果不是,我建议你再问一个关于你的整个管道的问题,这样我们就可以调整它以更好地工作。