MongoDB - 使用$ group在$ lookup后重绕$ unwind嵌套数组

时间:2016-09-14 13:14:51

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

MongoDB聚合在一分钟内呈指数级复杂化!

我到目前为止$unwind一个嵌套数组,然后通过unwinded嵌套数组中每个对象的$lookup执行_id。我最后的尝试是用$group来逆转展开。但是,我无法使用其原始属性名称以及每个文档的其余原始直接属性重建原始嵌入数组。

到目前为止,这是我的尝试:

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",
            emails: { "$first": "$emails" },
            profile: { "$first": "$profile" },
            universities: { "$push": "$profile.universities" }
        }
    }
]).pretty()

我得到的是这样的:

{
    "_id" : "A_USER_ID",
    "emails" : [
        {
            "address" : "AN_EMAIL_ADDRESS",
            "verified" : false
        }
    ],
    "profile" : {
        "name" : "NAME",
        "company" : "A COMPANY",
        "title" : "A TITLE",
        "phone" : "123-123-1234",
        "disabled" : false,
        "universities" : [
            {
                "_id" : "ID_1",
                "name" : "UNIVERSITY_NAME_1",
                "code" : "CODE_1",
                "styles" : {AN_OBJECT}
            }
        ]
    },
    "universities" : [
        [
            {
                "_id" : "ID_1",
                "name" : "UNIVERSITY_NAME_1",
                "code" : "CODE_1",
                "styles" : {AN_OBJECT}
            }
        ],
        [
            {
                "_id" : "ID_2",
                "name" : "UNIVERSITY_NAME_2",
                "code" : "CODE_2",
                "styles" : {AN_OBJECT}
            }
        ]
    ]
}

此结果有两个问题:

  1. 结果universities是一个包含一个对象的数组数组,因为$lookup返回了原始$profile.universities嵌套数组的单个元素数组。它应该只是一个对象数组。
  2. 生成的universities应将其原始位置嵌套在profiles下。我知道为什么原始的profile.universities就是这样,因为我使用的是$first运算符。我的意图是保留profile的所有原始属性,与保留原始嵌套universities数组的结合。
  3. 最终,我需要的是这样的事情:

    {
        "_id" : "A_USER_ID",
        "emails" : [
            {
                "address" : "AN_EMAIL_ADDRESS",
                "verified" : false
            }
        ],
        "profile" : {
            "name" : "NAME",
            "company" : "A COMPANY",
            "title" : "A TITLE",
            "phone" : "123-123-1234",
            "disabled" : false,
            "universities" : [
                {
                    "_id" : "ID_1",
                    "name" : "UNIVERSITY_NAME_1",
                    "code" : "CODE_1",
                    "styles" : {AN_OBJECT}
                },
                {
                    "_id" : "ID_2",
                    "name" : "UNIVERSITY_NAME_2",
                    "code" : "CODE_2",
                    "styles" : {AN_OBJECT}
                }
            ]
        }
    }
    

    我是否可以使用另一个运算符代替$group来实现此目的?或者我是否正确理解$group的目的?

    修改:这是原始帖子,用于上下文: If Mongo $lookup is a left outer join, then how come it excludes non-matching documents?

1 个答案:

答案 0 :(得分:17)

由于 $lookup 运算符会生成数组字段,因此您需要在 {{1}之前 $unwind 新字段管道来获得所需的结果:

$group