如果Mongo $ lookup是左外连接,那怎么会排除不匹配的文档呢?

时间:2016-09-13 22:26:04

标签: mongodb aggregation-framework lookup

标题说明了一切。如果一个文档根据其匹配字段没有产生任何匹配的外部文档,那么为什么它不包含在管道的结果集中呢?

我正在测试Mongo 3.2中的新聚合器,我已经通过首先展开来执行嵌套数组查找,然后将文档分组备份。我剩下的就是让结果包括所有不符合$lookup标准的本地文档,这就是我认为的“左外连接”的标准定义。

以下是查询:

db.users.aggregate([
    {
        $unwind: "$profile",
        $unwind: "$profile.universities"
    },
    {
        $lookup: {
            from: "universities",
            localField: "profile.universities._id",
            foreignField: "_id",
            as: "profile.universities"
        }
    },
    {
        $group: {
            _id: "$_id",
            universities: {
                $addToSet: "$profile.universities"
            }
        }
    }
]).pretty()

因此,如果我的user有一个空的profile.universities数组,那么我需要将它包含在结果集中,而不管$lookup返回任何匹配项,但它确实不。我怎么能这样做,以及为什么Mongo构建$lookup以这种方式运行的原因?

1 个答案:

答案 0 :(得分:23)

此行为与$lookup无关,这是因为$unwind的默认行为是省略缺少引用字段的文档或空数组。

即使profile.universities为空数组,也要保留未展开的文档,您可以将其preserveNullAndEmptyArrays选项设置为true

db.users.aggregate([
    {
        $unwind: "$profile",
        $unwind: {
            path: "$profile.universities",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $lookup: {
            from: "universities",
            localField: "profile.universities._id",
            foreignField: "_id",
            as: "profile.universities"
        }
    },
    {
        $group: {
            _id: "$_id",
            universities: {
                $addToSet: "$profile.universities"
            }
        }
    }
]).pretty()