简体   繁体   中英

mongodb aggregation with array and lookup

I have a MongoDB collection with documents in the following format collection name called post

{
    "_id" : ObjectId("5c88b225fac24431d947abad"),
    "user_id" : "5c87ad6c623f1e2bd4d041d0",
    "post_likes" : [ 
        {
            "post_user_id" : "5c87ad6c623f1e2bd4d041d0",
            "like_status" : true
        }, 
        {
            "post_user_id" : "5c88b42b71611926c055508b",
            "like_status" : true
        }
    ],
    "post_comments" : [ 
        {
            "comment_user_id" : "5c87ad6c623f1e2bd4d041d0",
            "comment_like" : "",
            "comment_description" : ""
        }, 
        {
            "comment_user_id" : "5c88b42b71611926c055508b",
            "comment_like" : "",
            "comment_description" : "nice post"
        }
    ]
}

i have another collection name called user_ptofile_info

{
    "_id" : ObjectId("5c923682c088564cf01056cb"),
    "user_id" : "5c87ad6c623f1e2bd4d041d0",
    "image_url" : "image/url",
    "user_name":"xxxxxxxx",
    "created_at" : "",
    "updated_at" : ""
}

requested output like
note:the post_user_id from user_ptofile_info and user_id from post are lookup and i need total count for post_likes and post comments also

{
    "_id" : ObjectId("5c88b225fac24431d947abad"),
    "user_id" : "5c87ad6c623f1e2bd4d041d0",
    "post_likes" : [ 
        {
            "post_user_id" : "5c87ad6c623f1e2bd4d041d0",
            "like_status" : true,
            "image_url" : "image/url",
            "user_name":"xxxxxxxx",
        }, 
        {
            "post_user_id" : "5c88b42b71611926c055508b",
            "like_status" : true,
            "image_url" : "image/url",
            "user_name":"xxxxxxxx",
        }
    ],
    "post_comments" : [ 
        {
            "comment_user_id" : "5c87ad6c623f1e2bd4d041d0",
            "comment_like" : "",
            "comment_description" : ""
        }, 
        {
            "comment_user_id" : "5c88b42b71611926c055508b",
            "comment_like" : "",
            "comment_description" : "nice post"
        }
    ]
}

You can use below aggregation:

db.post.aggregate([
    {
        $lookup: {
            from: "user_profile_info",
            let: { user_ids: "$post_likes.post_user_id" },
            pipeline: [
                { $match: { $expr: { $in: [ "$user_id", "$$user_ids" ] } } },
                { 
                    $project: {
                        post_user_id: "$user_id",
                        image_url: 1,
                        user_name: 1                        
                    }  
                }
            ],
            as: "users"
        }
    },
    {
        $project: {
            _id: 1,
            user_id: 1,
            post_likes: {
                $map: {
                    input: "$users",
                    as: "user",
                    in: {
                        post_user_id: "$$user.post_user_id",
                        image_url: "$$user.image_url",
                        user_name: "$$user.user_name",
                        like_status: {
                            $let: { 
                                vars: { 
                                    like: { 
                                        $arrayElemAt: [ 
                                            { $filter: { input: "$post_likes", as: "pl", cond: { $eq: [ "$$pl.post_user_id", "$$user.post_user_id" ] } } }, 0 
                                        ] 
                                    } 
                                },
                                in: "$$like.like_status"
                            }
                        }
                    }
                }
            },
            post_comments: 1
        }
    }
])

$lookup with custom pipeline (MongoDB 3.6 or newer) will allow you to get the data from user_profile_info for all users that are present in post_likes array. Then you need to "merge" users array with post_likes to get like_status . Since you have two arrays and you know that the same post_user_id appears in both of them you can use $map with $arrayElemAt and $filter to combine the data from both arrays.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM