如何获取引用对象的文档?

时间:2018-02-19 12:54:42

标签: mongodb mongodb-query aggregation-framework

我有三个集SubscribersAddressLanguages

Subscribers架构有以下记录

{
        "_id" : ObjectId("5a73fae80290f7eca89e99d4"),
        "FirstName" : "Rahul",
        "LastName" : "Shah",            
        "Address" : DBRef("Address", ObjectId("5a6ec9bda3baf2b516de5769")),            
        "Languages" : [
                DBRef("Languages", ObjectId("5a6304ffc3c3f119fc0e60c9")),
                DBRef("Languages", ObjectId("5a6ee970a3baf2b516de576b"))
        ]
}

Address架构有以下记录

{
        "_id" : ObjectId("5a6ec9bda3baf2b516de5769"),
        "Address1" : "Vastrapur,
        "Address2" : "Satellite",
        "City" : "Ahmedabad",
        "Country" : "India",
        "State" : "Gujarat",
        "ZipCode" : "380015",
        "PhoneNumber" : "(987)654-3210",
        "FaxNumber" : ""
}

Languages架构有以下记录

{
        "_id" : ObjectId("5a6304ffc3c3f119fc0e60c9"),
        "Name" : "English",
        "LanguageCulture" : "English",
        "IsDeleted" : false
}
{
        "_id" : ObjectId("5a6ee970a3baf2b516de576b"),
        "Name" : "Hindi",
        "LanguageCulture" : "Hindi",
        "IsDeleted" : false
}

我希望输出如下所示

{
    "_id" : ObjectId("5a73fae80290f7eca89e99d4"),
    "FirstName" : "Rahul",
    "LastName" : "Shah",
    "Address" : {
        "_id" : ObjectId("5a6ec9bda3baf2b516de5769"),
        "Address1" : "Vastrapur",
        "Address2" : " Satellite ",
        "City" : " Ahmedabad ",
        "Country" : " India ",
        "State" : " Gujarat ",
        "ZipCode" : " 380015 ",
        "PhoneNumber" : "(987)654 - 3210 ",
        "FaxNumber" : " "
    },
    "Languages" : [{
            "_id" : ObjectId(" 5a6304ffc3c3f119fc0e60c9 "),
            " Name" : " English ",
            "LanguageCulture" : " English ",
            "IsDeleted" : false
        }, {
            "_id" : ObjectId(" 5a6ee970a3baf2b516de576b "),
            "Name" : " Hindi ",
            "LanguageCulture" : " Hindi ",
            "IsDeleted" : false
        }
    ]
}

为此我正在进行聚合,如下所示

db.Subscribers.aggregate([{
            $project : {
                "FirstName" : 1,
                "LastName" : 1,
                Address : {
                    $let : {
                        vars : {
                            refParts : {
                                $objectToArray : "$$ROOT.Address"
                            }
                        },
                        in : "$$refParts"
                    }
                }
            }
        }, {
            $match : {
                "addressRefs" : {
                    $exists : true
                }
            }
        }, {
            $project : {
                "FirstName" : 1,
                "LastName" : 1,             
                "addressRefs" : {
                    $arrayElemAt : ["$addressRefs", 1]
                }
            }
        }, {
            $lookup : {
                from : "Addresses",
                localField : "addressRefs",
                foreignField : "_id",
                as : "address_data"
            }
        }, {
            $project : {
                "FirstName" : 1,
                "LastName" : 1,             
                "AddressUuid" : {
                    $arrayElemAt : ["$address_data.uuid", 0]
                }
            }
        }
    ])

1 个答案:

答案 0 :(得分:1)

你走了。由于您使用了DBRef,它并不漂亮,但由于以下SO答案,它可以完成工作:

Mongo how to $lookup with DBRef

db.Subscribers.aggregate([{
    $addFields: { 
        "Address": {$arrayElemAt: [{$objectToArray: "$Address"}, 1]}, // simple DBRef transformation if the field is not an array of DBRefs
        "Languages": {
            $map: { 
                input: { 
                    $map: {
                        input: "$Languages",
                        in: {
                            $arrayElemAt: [{$objectToArray: "$$this"}, 1]
                        },
                    }
                },
                in: "$$this.v"
            }
        }
    }
}, {
    $lookup: {
       from: "Address",
       localField: "Address.v", // note the .v here
       foreignField: "_id",
       as: "Address"
    }
}, {
    $lookup: {
       from: "Languages",
       localField: "Languages",
       foreignField: "_id",
       as: "Languages"
    }
}, {
    $addFields: {
        "Address": { $arrayElemAt: [ "$Address", 0 ] } // you can replace this step with an $unwind to 'flatten' the single-value array but you might want to use preserveNullAndEmptyArrays: true in order to cater for subscribers that come without valid Address references
    }
}])