Home > Back-end >  A way to join posts with users in mongoose
A way to join posts with users in mongoose

Time:01-09

I'm trying to make a social media app, got stuck in this situation where I don't know how to join posts with users,

I'm trying to get all the posts existing in the posts collection along with each post's user information, I used to have a function that finds the user, returns it, and adds it inside the post JSON for the front end but I figured there must be a better way to do it using inner joins, etc so in the front end I can loop through the posts result like for post in posts and access the information like post.content , post.author.avatar , post.author.username ...

this is the post schema:

const { Schema, model } = require('mongoose');

const PostSchema = new Schema({
    userId: {
        type: String,
        required: true,
    },
    content: {
        type: String,
        required: true,
        max: 500,
    },
    likes: {
        type: Array,
        default: []
    }
},
    { timestamps: true }
)

const PostModel = model('post', PostSchema);

module.exports = PostModel;

this is the method i use to create it ( i provide the userId and content) : enter image description here

here's the api method to get all posts

//get (all) posts
router.post('/feed/all', async (req, res) => {
    try {
        let feed = [];

        const currentUser = await getPostUser(req.body.userId)
        if (!currentUser)
            return res.status(404).json({ error: 'User not found' });

        // my posts
        const userPosts = currentUser ? (await Post.find({ userId: currentUser._id }).sort({ createdAt: -1 })) : {};
        userPosts.forEach(element => {
            feed.push(element)
        });

        // followed posts
        await Promise.all(
            currentUser.followings.map(async (followedId) => {
                let postUser = await getPostUser(followedId);
                let posts = (postUser) ? (await Post.find({ userId: followedId }).sort({ createdAt: -1 })) : {};
                posts.forEach(element => {
                    feed.push(element)
                });
            })
        );
        res.json(feed.sort(createdAt));

    } catch (error) {
        res.status(500).json({ error: error, message: 'drrr' })
    }
})

user schema:

const { Schema, model } = require('mongoose');

const UserSchema = new Schema(
    {
        username: {
            type: String,
            required: true,
            unique: true
        },
        password: {
            type: String,
            required: true,
        },
        firstname: {
            type: String,
            required: true,
        },
        lastname: {
            type: String,
            required: true,
        },
        email: {
            type: String,
            required: true
        },
        avatar: {
            type: String,
            default: "https://w7.pngwing.com/pngs/419/473/png-transparent-computer-icons-user-profile-login-user-heroes-sphere-black-thumbnail.png"
        },
        bio: {
            type: String,
            default: ""
        },
        followers: {
            type: Array,
            default: []
        },
        followings: {
            type: Array,
            default: []
        },
        isAdmin: {
            type: Boolean,
            default: false
        },
        isMod: {
            type: Boolean,
            default: false
        }
    },
    { timestamps: true }
)

const UserModel = model('user', UserSchema);

module.exports = UserModel;

CodePudding user response:

  • Firstly, You can change the post schema like this to reference to the users schema

const { Schema, model } = require('mongoose');

const PostSchema = new Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'user',
        required:true
    },
    content: {
        type: String,
        required: true,
        max: 500,
    },
    likes: {
        type: Array,
        default: []
    }
},
    { timestamps: true }
)

const PostModel = model('post', PostSchema);

module.exports = PostModel;

  • Then we are going to use the populate method to return the posts with users information like this

//get (all) posts
router.post('/feed/all', async (req, res) => {
    try {
        let feed = [];

        const currentUser = await getPostUser(req.body.userId)
        if (!currentUser)
            return res.status(404).json({ error: 'User not found' });

        // my posts
        if(currentUser){
          const userPosts =await Post
          .find({ userId: currentUser._id }).sort({ createdAt: -1   })
          .populate('userId','_id username firstname lastname email avatar bio followers followings')
        }
        

        // followed posts
        await Promise.all(
            currentUser.followings.map(async (followedId) => {
                let postUser = await getPostUser(followedId);
                let posts = (postUser) ? (await Post.find({ userId: followedId }).sort({ createdAt: -1 })) : {};
                posts.forEach(element => {
                    feed.push(element)
                });
            })
        );
        res.json(feed.sort(createdAt));

    } catch (error) {
        res.status(500).json({ error: error, message: 'drrr' })
    }
})

  •  Tags:  
  • Related