Home > Software design >  how to sort after lookup and project aggregation in mongodb?
how to sort after lookup and project aggregation in mongodb?

Time:03-30

I have 2 Collections one for users and other for posts(Posts colllection have _id of users as postedBy). In users collection each user is having friends array which have _id of users in it.I want to get all the Posts of My friends and mine post in sorted order(sorted By CreatedAt).

This is my Userschema in which i am having friends array of mongoose object type ref to user collection, here i'm storing users id who is friend. `//UserSchema

const userSchema = new Schema({
    profileImg : {
        type: String,
    },
    name: {
        type: String,
        required: [true, 'Please Enter Your Name!']
    },
    about: {
        type: String,
    },
    email: {
        type: String,
        required: [true, 'Please Enter Email!'],
        unique: [true, 'Already Registered!'],
        match: [/\S @\S \.\S /, 'is invalid!']
    },
    password: {
        type: String,
        required: [true, 'Please Enter Your Password!'],
    },
    friends: [{
        type: mongoose.Types.ObjectId,
        ref: 'USER'
    }],
    address: {
        line1: {
            type: String,
            required: [true, 'Please Enter Your Address!']
        },
        line2: {
            type: String
        },
        city: {
            type: String,
            required: [true, 'Please Enter Your City!']
        },
        state: {
            type: String,
            required: [true, 'Please Enter Your State!']
        },

    }
}, { timestamps: true })

This is my Post Schema where userId is ref to users collection and here the _id of user who is uploading post is saved. //POST SCHEMA

const postSchema = new Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "USER",
        required: true
    },
    postImage: {
        type: String,
        required: [true, 'Please Upload the Image!']
    },
    caption: {
        type: String
    },
    likes: [likeSchema],
    comments: [commentSchema]

}, { timestamps: true })

`

What I am Doing:

1st I am finding the user through _id 2nd from found user's friend array ,lookup in posts collection to get post of friends 3rd Now to get owns post again look up in post collection with own _id 4th concat the both array obtain from friend post and user post as Posts

Now here after step 4 i want to sort the Posts by createdAt but its not working.. How to sort it?

const posts = await User.aggregate([
            {
                $match: {
                    _id: mongoose.Types.ObjectId(req.user_id)
                }
            },
            {
                $lookup: {
                    from: "posts",
                    localField: "friends",
                    foreignField: "userId",
                    as: "friendposts"
                }
            },

            {
                $lookup: {
                    from: "posts",
                    localField: "_id",
                    foreignField: "userId",
                    as: "userposts"
                }
            },
            {
                $project: {
                    "Posts": {
                        $concatArrays: ["$friendposts", "$userposts"]
                    },
                    _id: 0
                }
            }


        ])

CodePudding user response:

you can use 1 lookup instead of 2 . for sorting you have 3 ways

  • sort in the code level (using sort function)
  • use $unwind $sort and group (if mongo db version is less than 5.2)
  • use $sortArray (applicable for mongodb version 5.2 )

if using 2nd method.

User.aggregate([
  {
    '$match': {
      '_id': mongoose.Types.ObjectId(req.user_id)
    }
  }, {
    '$addFields': {
      'users': {
        '$concatArrays': [
          '$friends', [
            mongoose.Types.ObjectId(req.user_id)
          ]
        ]
      }
    }
  }, {
    '$lookup': {
      'from': 'posts', 
      'localField': 'users', 
      'foreignField': 'userId', 
      'as': 'posts'
    }
  }, {
    '$unwind': {
      'path': '$posts'
    }
  }, {
    '$sort': {
      'posts.createdAt': -1
    }
  }, {
    '$group': {
      '_id': '$_id', 
      'posts': {
        '$push': '$posts'
      }, 
      'name': {
        '$first': '$name'
      }
    }
  }
])

you can add any other field needed in final response like wise i added name .

  • Related