如何使用lambda函数在mongodb中的两个集合之间进行多个联接?

时间:2019-08-14 14:08:52

标签: mongodb aws-lambda pymongo

我有两个集合1)user_posts 2)user_profile。找到以下收集数据以供参考。

1)user_posts集合

_id :ObjectId("5d519f861c9d4400005ebd1b")
userid : ObjectId("5d518caed55bc00001d235c1")
media : "hello.jpg"
type : "jpg"
created : " "
modified : " "
like : Array
       0 : Object
           userid : ObjectId("5d518caed55bc00001d235c1")
           status : "like"
       1 : Object
           userid : ObjectId("5d518da6d55bc00001d235c2")
           status : "happy"
comment : Array
       0 : Object
           userid : ObjectId("5d518caed55bc00001d235c1")
           comment : "hello"
       1 : Object
           userid : ObjectId("5d518da6d55bc00001d235c2")
           comment : "welcome"
share : Array
       0 : Object
           userid : ObjectId("5d518caed55bc00001d235c1")
           status : "shared"
       1 : Object
           userid : ObjectId("5d518da6d55bc00001d235c2")
           status : "shared"

2)User_profile集合

 _id : ObjectId("5d518caed55bc00001d235c1")
 username : "ramesh",
 photo :  " ",
 created : " ",
 modified : " "

 _id : ObjectId("5d518da6d55bc00001d235c2")
 username : "shekar",
 photo :  " ",
 created : " ",
 modified : " "

现在,我尝试从lambda函数中的user_profile获取配置文件详细信息。但我没有得到细节。找到下面的lambda函数代码。

def lambda_handler(event, context):

print("Received event: " + json.dumps(event, indent=1))

user_posts = db.user_posts

Userid = event['userid']
uid = ObjectId(Userid)

dispost = list(user_posts.aggregate([{
"$match" : { "userid" : uid }
},
{ "$graphLookup" : 
     {
       "from" : "user_profile",
       "startWith" : "$like.userid",
       "connectFromField" : "like.userid",
       "connectToField" : "_id",
       "as" : "userdetails"
     }
},
{ "$graphLookup" : 
     {
       "from" : "user_profile",
       "startWith" : "$comment.userid",
       "connectFromField" : "comment.userid",
       "connectToField" : "_id",
       "as" : "userdetails1"
     }
}
{ "$graphLookup" : 
     {
       "from" : "user_profile",
       "startWith" : "$share.userid",
       "connectFromField" : "share.userid",
       "connectToField" : "_id",
       "as" : "userdetails2"
     }
}
]))     
disair = json.dumps(dispost, default=json_util.default)
return json.loads(disair)

但是我没有得到输出。我需要下面这样的输出。

_id :ObjectId("5d519f861c9d4400005ebd1b")
userid : ObjectId("5d518caed55bc00001d235c1")
username : "ramesh"
photo : " ",
media : "hello.jpg"
type : "jpg"
created : " "
modified : " "
like : Array
       0 : Object
           userid : ObjectId("5d518caed55bc00001d235c1")
           status : "like"
           username : "ramesh"
           photo : " "
       1 : Object
           username : "shekar"
           photo : " "
           userid : ObjectId("5d518da6d55bc00001d235c2")
           status : "happy"
           username : "shekar"
           photo : " "
comment : Array
       0 : Object
           userid : ObjectId("5d518caed55bc00001d235c1")
           comment : "hello"
           username : "ramesh"
           photo : " "
       1 : Object
           userid : ObjectId("5d518da6d55bc00001d235c2")
           comment : "welocme"
           username : "shekar"
           photo : " "
share : Array
       0 : Object
           userid : ObjectId("5d518caed55bc00001d235c1")
           status : "shared"
           username : "ramesh"
           photo : " "
       1 : Object
           userid : ObjectId("5d518da6d55bc00001d235c2")
           status : "shared"
           username : "shekar"
           photo : " "

能帮我解决问题吗?预先感谢。

2 个答案:

答案 0 :(得分:0)

请检查以下内容:

    db.user_posts.aggregate([{ $match: { _id: ObjectId("5d519f861c9d4400005ebd1b") } }, {
    $lookup:
    {
        from: "user_profile",
        let: { userIdToBeCompared: "$userid", like: '$like', comment: '$comment', share: '$share' },
        pipeline: [
            {
                $match:
                {
                    $expr:
                    {

                        $or:
                            [
                                { $eq: ["$_id", "$$userIdToBeCompared"] },
                                { $in: ["$_id", "$$like.userid"] },
                                { $in: ["$_id", "$$comment.userid"] },
                                { $in: ["$_id", "$$share.userid"] }
                            ]
                    }
                }
            }

        ],
        as: "data"
    }
}])

好吧,您的需求中有太​​多事情要做,而对于当前的数据结构来说,从数据库层实现您的所有需求可能不是一件容易的事,也不是一个好主意,因此,在这里最后的回应 data 将具有您所需的所有映射,将其获取到您的代码中,并根据用户ID将所需的详细信息提取到每个部分,从我尝试过的情况开始,我认为这是实现的理想方案!

答案 1 :(得分:0)

请检查以下内容:

db.collection("user_posts").aggregate(
{ $match: {"userid" : uid}},
{ $unwind: '$like' },
{ $lookup: { from: "users", localField: "like.userid", foreignField: "_id", as: 
"users" }},
{ $group: {
    _id: "$_id",
    like: { $push: { $mergeObjects: ['$like', { $arrayElemAt: [ "$users", 0 ] } ]}},
    data: { $first: "$$ROOT" }
}},
{ $replaceRoot: { newRoot: { $mergeObjects: ['$data', { like: "$like"} ]} } },
{ $unwind: '$comment' },
{ $lookup: { from: "users", localField: "comment.userid", foreignField: "_id", as: 
 "users" }},
{ $group: {
    _id: "$_id",
        comment: { $push: { $mergeObjects: ['$comment', { $arrayElemAt: [ "$users", 0 
 ] } ]}},
        data: { $first: "$$ROOT" }
}},
{ $replaceRoot: { newRoot: { $mergeObjects: ['$data', { comment: "$comment"} ]} } },
{ $unwind: '$share' },
{ $lookup: { from: "users", localField: "share.userid", foreignField: "_id", as: 
"users" }},
{ $group: {
    _id: "$_id",
    share: { $push: { $mergeObjects: ['$share', { $arrayElemAt: [ "$users", 0 ] } 
]}},
    data: { $first: "$$ROOT" }
}},
{ $replaceRoot: { newRoot: { $mergeObjects: ['$data', { share: "$share"} ]} } },
{ $project: { users: 0 }}
)

您将获得输出,根据您的要求更改项目聚合中的添加/删除字段名称