Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb subquery in aggregation

I have followers collection in mongodb like below:

[{
    user : <userId> ,
    followers : [
        {
            user : <userId>
            , createdOn : <Date>
            ,...
        }
        ,
        {
            user : <userId>
            , createdOn : <Date>
            ,...
        }
    ]
},
{
    user : <userId> ,
    followers : [
        {
            user : <userId>
            , createdOn : <Date>
            ,...
        }
        ,
        {
            user : <userId>
            , createdOn : <Date>
            ,...
        }
    ]
}]

When users requests to /api/users/<userId>/followers I am trying to provide all the followers of user <userId>. Additionally I am also trying to set a flag to denote if the particular follower of <userId> is followed by the loggedIn user or not. I am trying to output something like below :

{
    user : <userId>
    , followers : [
        {
            user : <userId>
            , isFollowing : <Boolean>
        }
        ,
        {
            user : <userId>
            , isFollowing : <Boolean>
        }
    ]
}

I give a try and my unsuccessful attempt looks like this :

app.get('/users/:userId/followers', function(req, res) {
    var userId = req.params.userId;
    var loginUser = req.user._id; // I am using passport for user authentication
    var Follower = mongoose.model('followers'); // I am using mongoose also
    var DocumentObjectId = mongoose.Types.ObjectId;

    Follower.aggregate([
         {$match : { user : DocumentObjectId(userId)}}
        , {$project : {"followers" : 1, "_id" : 0}}
        , {$unwind : "$followers"}
        , {$group : {
            _id : {"user : "$user"}
            , "followers" : {$push:{
                "user" : "$followers.user"
                , "isFollowing" : {$and : [{user: "$followers.user"}, {"followers.user" : loginUser}]}
            }}
        }}
    ])

})

But I am getting this error from mongodb : exception: dotted field names are only allowed at the top level

What should I do to know either particular follower is being followed by logged in user. So that I could display Follow or Unfollow button in UI when some user views another users followers.

like image 402
Lekhnath Avatar asked Feb 25 '26 13:02

Lekhnath


1 Answers

You need to use the aggregation pipeline as below:

  • Match the user with the corresponding userId.
  • Unwind the followers array.
  • For each un-winded follower, project a field named isFollowing which conditionally states if he is the logged in user, implying he is a follower of the searched for user.
  • Group back the un-winded records based on the user, and compose an array of followers with the extra isFollowing field.

The Code:

var loginUser = 2;
var userId = 3; 
var documentObjectId = mongoose.Types.ObjectId;
Follower.aggregate(
{$match:{"user":documentObjectId(userId)}},
{$unwind:"$followers"},
{$project:{"user":1,"_id":0,
           "follower":"$followers.user",
           "isFollowing":{$cond:[{$eq:["$followers.user",loginUser]}
                         ,true,false]}}},
{$group:{"_id":"$user",
         "followers":{$push: {"user":"$follower",
                              "isFollowing":"$isFollowing"}}}},
function(err,resp){//handle response}
);

But I am getting this error from mongodb : exception: dotted field names are only allowed at the top level

You cant do {"followers.user" : loginUser} in a group by stage, this is a criteria statement which can be applied only in the $match stage. To see all the applicable group by operators refer:operators.

like image 138
BatScream Avatar answered Feb 28 '26 06:02

BatScream



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!