Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb Mongo聚合根据在另一个表中是否找到一个表中的记录排除这些记录_Mongodb_Aggregation Framework - Fatal编程技术网

Mongodb Mongo聚合根据在另一个表中是否找到一个表中的记录排除这些记录

Mongodb Mongo聚合根据在另一个表中是否找到一个表中的记录排除这些记录,mongodb,aggregation-framework,Mongodb,Aggregation Framework,公寓桌 { "_id": "AAA", "name": "Apartment AAA" }, { "_id": "BBB", "name": "Apartment BBB" }, { "_id": "CCC", "name": "Apartment CCC" }, { "_id": "DDD", "name": "Apartment DDD" }, { "_id": "EEE", "name": "Apartment

公寓桌

{
    "_id": "AAA",
    "name": "Apartment AAA"
},
{
    "_id": "BBB",
    "name": "Apartment BBB"
},
{
    "_id": "CCC",
    "name": "Apartment CCC"
},
{
    "_id": "DDD",
    "name": "Apartment DDD"
},
{
    "_id": "EEE",
    "name": "Apartment EEE"
}
{
    "_id": 1,
    "apartmentID": "AAA",
    "checkin": 1490000000,
    "checkout": 1499000000
}
{
    "_id": 2,
    "apartmentID": "BBB",
    "checkin": 1500000000,
    "checkout": 1590000000
}
{
    "_id": 3,
    "apartmentID": "CCC",
    "checkin": 1490000000,
    "checkout": 1499000000
}
{
    "_id": 4,
    "apartmentID": "DDD",
    "checkin": 1500000000,
    "checkout": 1590000000
}
预订表

{
    "_id": "AAA",
    "name": "Apartment AAA"
},
{
    "_id": "BBB",
    "name": "Apartment BBB"
},
{
    "_id": "CCC",
    "name": "Apartment CCC"
},
{
    "_id": "DDD",
    "name": "Apartment DDD"
},
{
    "_id": "EEE",
    "name": "Apartment EEE"
}
{
    "_id": 1,
    "apartmentID": "AAA",
    "checkin": 1490000000,
    "checkout": 1499000000
}
{
    "_id": 2,
    "apartmentID": "BBB",
    "checkin": 1500000000,
    "checkout": 1590000000
}
{
    "_id": 3,
    "apartmentID": "CCC",
    "checkin": 1490000000,
    "checkout": 1499000000
}
{
    "_id": 4,
    "apartmentID": "DDD",
    "checkin": 1500000000,
    "checkout": 1590000000
}
我需要找到所有在“
1510000000
”和“
1520000000
”之间没有预订的“
name
”公寓

在这种情况下,结果应为:

{
    "name": "Apartment AAA"
},
{
    "name": "Apartment CCC"
},
{
    "name": "Apartment EEE"
}
请注意,EEE公寓没有任何预订

通常我会将所有属性放入一个数组,然后将所有预订放入一个数组,然后在javascript中运行一些循环以查找可用的公寓

问题:是否有一种方法可以在一个mongodb聚合管道中实现这一点,并且只返回可用公寓的“名称”

我以前的查找:

db.apartment.aggregate([
{
    $match: {}
},
{ 
    $project: { 
        "name": 1
    }
}


db.booking.aggregate([
{
    $match: {
        checkin: {$lte: 1520000000},
        checkout: {$gte: 1510000000}
    }
},
{ 
    $project: { 
        "apartmentID": 1
    }
}

从3.2版开始,您可以使用运算符外部联接两个集合:

db.apartment.aggregate([
{
    $lookup: {
        from: "booking",
        localField: "_id",
        foreignField: "apartmentID",
        as: "booking"
    }
},
{
    $unwind: { path: "$booking", preserveNullAndEmptyArrays: true }
},
{
    $match: {
        $or: [
          { "booking": {$exists: false }},
          { "booking.checkin": {$gte: 1520000000} },
          { "booking.checkout": {$lte: 1510000000} }
        ]
    }
},
{
    $group: { _id: "$name" }
},
{
    $project: { _id: 0, name: "$_id" }
}
])
输出:

{
    "name" : "Apartment AAA"
},
{
    "name" : "Apartment CCC"
},
{
    "name" : "Apartment EEE"
}

详情:

第一阶段创建了公寓与预订的外部连接。此阶段产生的结果如下所示:

{
    "_id": "AAA",
    "name": "Apartment AAA",
    "booking": [ 
        {
          "_id": 1,
          "apartmentID": "AAA",
          "checkin": 1490000000,
          "checkout": 1499000000
        },
        {
          "_id": 5,
          "apartmentID": "AAA",
          "checkin": 1500000000,
          "checkout": 1590000000
        },
    ]
}
...
{
    "_id": "EEE",
    "name": "Apartment EEE"
}
请注意,如果公寓AAA有多个预订,则所有预订文档都将添加到
预订
公寓数组中。另外请注意,没有预订的公寓将不会有
预订
阵列。接下来,我们将展开联接的bookings数组以摆脱该数组,并使用单个booking生成扁平的公寓对象(如果有):


接下来,我们按公寓名称进行过滤和分组过滤结果(因为一个公寓可以有多个不属于给定范围的预订)。最后一个阶段是投影。

自3.2版以来,您可以使用运算符将两个集合外部连接起来:

db.apartment.aggregate([
{
    $lookup: {
        from: "booking",
        localField: "_id",
        foreignField: "apartmentID",
        as: "booking"
    }
},
{
    $unwind: { path: "$booking", preserveNullAndEmptyArrays: true }
},
{
    $match: {
        $or: [
          { "booking": {$exists: false }},
          { "booking.checkin": {$gte: 1520000000} },
          { "booking.checkout": {$lte: 1510000000} }
        ]
    }
},
{
    $group: { _id: "$name" }
},
{
    $project: { _id: 0, name: "$_id" }
}
])
输出:

{
    "name" : "Apartment AAA"
},
{
    "name" : "Apartment CCC"
},
{
    "name" : "Apartment EEE"
}

详情:

第一阶段创建了公寓与预订的外部连接。此阶段产生的结果如下所示:

{
    "_id": "AAA",
    "name": "Apartment AAA",
    "booking": [ 
        {
          "_id": 1,
          "apartmentID": "AAA",
          "checkin": 1490000000,
          "checkout": 1499000000
        },
        {
          "_id": 5,
          "apartmentID": "AAA",
          "checkin": 1500000000,
          "checkout": 1590000000
        },
    ]
}
...
{
    "_id": "EEE",
    "name": "Apartment EEE"
}
请注意,如果公寓AAA有多个预订,则所有预订文档都将添加到
预订
公寓数组中。另外请注意,没有预订的公寓将不会有
预订
阵列。接下来,我们将展开联接的bookings数组以摆脱该数组,并使用单个booking生成扁平的公寓对象(如果有):


接下来,我们按公寓名称进行过滤和分组过滤结果(因为一个公寓可以有多个不属于给定范围的预订)。最后一个阶段是投影。

您可以使用
$not+$elemMatch
查找公寓预订是否有人

$elemMatch
查找是否有符合查询条件的已入住公寓,后跟
$not
,在没有已入住的预订时返回公寓文档

差不多

   db.apartment.aggregate({
    $lookup: {
        from: "booking",
        localField: "_id",
        foreignField: "apartmentID",
        as: "bookings"
    }
   }, {
    $match: {
        "bookings": {
            $not: {
                $elemMatch: {
                    checkin: {
                        $lte: 1520000000
                    },
                    checkout: {
                        $gte: 1510000000
                    }
                }
            }
        }
    }
   }, {
    $project: {
        _id: 0,
        name: 1
    }
   })

您可以使用
$not+$elemMatch
查找公寓预订是否有人

$elemMatch
查找是否有符合查询条件的已入住公寓,后跟
$not
,在没有已入住的预订时返回公寓文档

差不多

   db.apartment.aggregate({
    $lookup: {
        from: "booking",
        localField: "_id",
        foreignField: "apartmentID",
        as: "bookings"
    }
   }, {
    $match: {
        "bookings": {
            $not: {
                $elemMatch: {
                    checkin: {
                        $lte: 1520000000
                    },
                    checkout: {
                        $gte: 1510000000
                    }
                }
            }
        }
    }
   }, {
    $project: {
        _id: 0,
        name: 1
    }
   })

嗯,这个会给我与我需要的相反的东西(我需要没有人住的公寓),这会给我一个
ID
name
中,而不是
公寓。name
。最后,它也不包括公寓EEE,对不起,错过了这一部分。现在,aggregate只选择在给定范围内没有预订或没有预订的房间。这个房间将为我提供与我需要的相反的东西(我需要没有人住的公寓),这将在
名称中为我提供
ID
,而不是
公寓。名称
。最后,它也不包括公寓EEE,对不起,错过了这一部分。现在“聚合”只选择在给定范围内没有预订或没有预订的房间。请再次单击-D我不知道$elemMatch的事。所以你阅读所有的公寓,然后进行预订查询,然后在预订后进行匹配。这很聪明,我没想过把数学往下推。其实很酷。问题:我想添加更多的$lookup以从其他表获取数据,我应该在$match之后这样做吗?是的,您可以在$match之后添加更多的阶段。这取决于你要做什么。基于这一点,你可能需要先放松,然后才能查找。酷酷的Veeram-我再次向你鞠躬哦,强大的Mongo大师:-)谢谢你的好话,但我根本不是大师。我很高兴在这个过程中学习和帮助他人。维拉姆再次出击!:-D我不知道$elemMatch的事。所以你阅读所有的公寓,然后进行预订查询,然后在预订后进行匹配。这很聪明,我没想过把数学往下推。其实很酷。问题:我想添加更多的$lookup以从其他表获取数据,我应该在$match之后这样做吗?是的,您可以在$match之后添加更多的阶段。这取决于你要做什么。基于这一点,你可能需要先放松,然后才能查找。酷酷的Veeram-我再次向你鞠躬哦,强大的Mongo大师:-)谢谢你的好话,但我根本不是大师。我很高兴在这个过程中学习和帮助他人。