User model
const Schema = mongoose.Schema
const userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, reuired: true },
password: { type: String, required: true },
posts:[{ type: Schema.Types.ObjectId, ref: "Posts" }]
}, { timestamps: true })
Post model
const Schema = mongoose.Schema;
const postSchema = new Schema({
title: { type: String, required: true },
content: { type: String, required: true },
user: { type: Schema.Types.ObjectId, ref: "User" },
}, { timestamps: true }
endpoint for getting all posts with all users information
listPostsWithUsers: (req, res, next) => {
Post.find({}, (error, posts) => {
if (error) {
return res.status(500).json({ error: "something went wrong" })
} else if (!posts) {
return res.status(400).json({ msg: "sorry no posts" })
} else if (posts) {
return res.status(200).json({ posts })
}
})
}
The output should be the returned posts with the user object so that I can identify which post the user has posted.
Now, my question is how do I apply populate()
method in the above endpoint. Mostly all examples are with exec()
function but I've seen no example with callbacks. It's kind of a syntax problem.
Thank you.
Update#1
: The result I'm getting currently.
{
"posts": [
{
"_id": "5e65cce5ebddec0c5cc925ab",
"title": "Neil's Post",
"content": "post by neil.",
"createdAt": "2020-03-09T04:58:13.900Z",
"updatedAt": "2020-03-09T04:58:13.900Z",
"__v": 0
},
{
"_id": "5e65cd32ebddec0c5cc925ad",
"title": "Slash's post",
"content": "post by slash.",
"createdAt": "2020-03-09T04:59:30.180Z",
"updatedAt": "2020-03-09T04:59:30.180Z",
"__v": 0
},
{
"_id": "5e65f430a989612916636e8d",
"title": "Jimmy's post",
"content": "post by jimmy",
"createdAt": "2020-03-09T07:45:52.664Z",
"updatedAt": "2020-03-09T07:45:52.664Z",
"__v": 0
}
]
}
Update#2
users
collection.
{
"users": [
{
"posts": [],
"_id": "5e65ccbeebddec0c5cc925aa",
"username": "Neil",
"email": "neily888@gmail.com",
"password": "$2b$10$AHHRKuCX3nakMs8hdVj0DuwD5uL0/TJwkJyKZYR/TXPTrIo9f80IW",
"createdAt": "2020-03-09T04:57:35.008Z",
"updatedAt": "2020-03-09T04:57:35.008Z",
"__v": 0
},
{
"posts": [],
"_id": "5e65cd0eebddec0c5cc925ac",
"username": "Slash",
"email": "slash938@gmail.com",
"password": "$2b$10$QQX/CFJjmpGdBAEogQ4XO.1e1ZowuPCX7pJcHTUav7NfatGgp6sa6",
"createdAt": "2020-03-09T04:58:54.520Z",
"updatedAt": "2020-03-09T04:58:54.520Z",
"__v": 0
},
{
"posts": [],
"_id": "5e65f408a989612916636e8c",
"username": "Jimmy",
"email": "jimmy787@gmail.com",
"password": "$2b$10$/DjwWYIlNswgmYt3vo7hJeNupfBdFGe7p77uisYUViKv8IdhasDC.",
"createdAt": "2020-03-09T07:45:12.293Z",
"updatedAt": "2020-03-09T07:45:12.293Z",
"__v": 0
}
]
}
Update#3
:
usersController
const User = require("../models/User")
module.exports = {
createUser: (req, res) => {
User.create(req.body, (err, createdUser) => {
if (err) console.log(err)
res.json({createdUser})
})
},
listUsers: (res) => {
User.find({}, (err, users) => {
if (err) console.log(err)
res.json({users})
})
},
getUser: (req, res) => {
User.findById(req.params.id, (err, user) => {
if (err) console.log(err)
return res.json({user})
})
},
updateUser: (req, res) => {
const user = {
username: req.body.username,
email: req.body.email,
password: req.body.password
}
User.findOneAndUpdate(req.params.id, user, { new: true }, (err, updatedUser) => {
if (err) console.log(err)
res.json({updatedUser})
})
},
deleteUser: (req, res) => {
User.findByIdAndDelete(req.params.id, (err, deleteduser) => {
if (err) console.log(err)
return res.status(200).json({ user: deleteduser })
})
}
}
postsController
const Post = require("../models/Post")
module.exports = {
createPost: (req, res) => {
const data = {
title: req.body.title,
description: req.body.description,
}
Post.create(data, (err, newPost) => {
if (err) console.log(err);
return res.status(200).json({ newPost })
})
},
listPosts: (res) => {
Post.find({}, async (err, posts) => {
if (err) console.log(err);
posts = await Post.populate(posts, {
path: "user",
model: "User"
})
return res.status(200).json({ posts })
})
},
findPost: (req, res) => {
Post.findById(req.params.id, (err, post) => {
if (err) console.log(err);
return res.json({ post })
}
)
},
updatePost: (req, res) => {
const post = {
title: req.body.title,
description: req.body.description
}
Post.findByIdAndUpdate(req.params.id, post, { new: true },(err, updatedPost) => {
if (err) console.log(err);
return res.status(200).json({ updatedPost })
})
},
deletePost: (req, res) => {
Post.findByIdAndDelete(req.params.id, (err, deletedPost) => {
if (err) console.log(err);
return res.status(200).json({ deletedPost })
})
}
}
Update#4
router.get("/posts/:id", usersController.getUserPosts)
`
getUserPosts: (req, res) => {
User.findById(req.params.id, async (err, user) => {
if (err) {
return res.status(500).json({ error: "Server error" })
} else if (!user) {
return res.status(400).json({ error: "No user" })
} else if (user) {
user = await User.populate("user", {
path: "posts",
model: "Post"
})
return res.status(200).json({ user })
}
})
}
I suggest you to use mongoose populate.
listPostsWithUsers : (req, res, next) => {
Post.find({}).populate('user').exec(function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
})
}
You can refer this official mongoose populate document
You can even populate as many fields required by using populate as
populate([{ path: 'user' }, { path: 'book', select: { author: 1 } }])
with the help of select in populate, you can project the required fields (get only those fields from populated collection.)
createPost: (req, res) => {
const data = {
title: req.body.title,
description: req.body.description,
user: req.user._id,
}
Post.create(data, (err, newPost) => {
if (err) console.log(err);
return res.status(200).json({ newPost })
})
You will need to add user field in post while creating. take user id from token or from query and you would be good to go.
getUserPosts: (req, res) => {
User.findById(req.params.id).populate([{ path: 'posts' }])
.exec(function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
}
You are finding data in user module and you want to populate post data, so you just need to say which field you want to populate as you have already defined on field which model to refer by adding ref with that field in mongoose schema.
getUserPosts: (req, res) => {
User.findById(req.params.id, async (err, user) => {
if (err) {
return res.status(500).json({ error: "Server error" })
} else if (!user) {
return res.status(400).json({ error: "No user" })
} else if (user) {
user = await User.populate("posts")
return res.status(200).json({ user })
}
})
}
This should also work for you.