0

My question is easy enough. i just cant come up with the logic myself. I created an api for a social media website using MERN stack. I added a 'get timeline' route that returns all the posts of the people that the current user has friended in addition to the own user's posts. Whenever a user adds a friend, the id of that friend is stored in an array in the mongoDB model. How do i filter the data coming back from the post model to only return the posts of the friend IDs inside the friends array in addition to the posts of the current user also.

The User model:

const UserSchema = new mongoose.Schema({
    firstName: {
        type: String,
        required: [true, 'please provide your first name'],
        maxlength: 50,
        minlength: 2
    },
    lastName: {
        type: String,
        required: [true, 'please provide your last name'],
        maxlength: 50,
        minlength: 2
    },
    email: {
        type: String,
        required: [true, 'please provide an email'], 
        match: [
            /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
            'Please provide a valid email',
        ],
        unique: true,
    },
    password: {
        type: String,
        required: [true, 'please provide a password'],
        minlength: 8
    },
    image: {
        type: String,
    },
    friends: {
        type: Array,
        default: [],
    },
    location: String,
    occupation: String,
},
    { timestamps: true }
)

The timeline route:

router.get("/:id/timeline", getTimelinePosts)

The add or remove friend controller:

const addRemoveFriend = async (req, res) => {
    const {id: userId, friendId} = req.params
    const user = await User.findOne({_id: userId}) 
    const friend = await User.findOne ({_id: friendId})


    if(user.friends.includes(friendId)){
        user.friends = user.friends.filter((_id) => _id !== friendId)
        friend.friends = friend.friends.filter((_id) => _id !== userId);
    }else{
        user.friends.push(friendId);
        friend.friends.push(userId);
    }
    await user.save();
    await friend.save();

    

    
    const friends = await Promise.all(
      user.friends.map((_id) => User.findById(_id))
    );
    const formattedFriends = friends.map(
      ({ _id, firstName, lastName, location, image}) => {
            return { _id, firstName, lastName, location, image};
      }
    );


    res.status(200).json({formattedFriends});
}
gerard
  • 221
  • 1
  • 2
  • 10

1 Answers1

1

You can use $in Operator to iterate over all the friends Ids and get the related post.

router.get("/get-timeline", async (req, res) => {
    try {

        const Posts = await mongoose.connection.db.collection('post')

        const { id: userId } = req.params

        //get the user record
        const user = await User.findOne({ _id: userId })

        //List of friends Id
        const friendsList = user.friends
        
        // I'm assuming in Post collection you have the field createdBy(assuming) to refer which user has created the post.
        let postData = await Posts.find({ createdBy: { $in: friendsList } })

        if (postData) {
            return res.status(200).json({ success: true, data: postData })
        } else {
            console.log("Error while getting post data", err)
            return res.status(500).json({ success: false, message: err })
        }
    } catch (err) {
        console.log("Error while getting post data", err)
        return res.status(500).json({ success: false, message: err })
    }

})
Anurag Tripathi
  • 784
  • 1
  • 13
  • 13