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) :

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' })
}
})
