I have created 2 models namely user, article. Their data structure are like below;
const userSchema = Schema({
name: String,
email: String,
password: String
});
const User = mongoose.model(‘user’, userSchema);
module.exports = User;
——
const articleSchema = Schema({
liked: Array, // liked contains users’ _id who like this article
content: String
})
const Article = mongoose.model(‘article’, articleSchema);
module.exports = Article
——
I want to get all articles by page size of 10 and each article get populated some users’ info who like this article.
For example, let’s imagine the data of user table and article table like this:
users = [
{
_id: 1,
name: ‘a’,
email: ‘a.com’,
password: ‘a’
},
{
_id: 2,
name: ‘b’,
email: ‘b.com’,
password: ‘b’
}
]
articles = [
{
_id: 1,
liked: [1,2],
content: “a&b”
},
{
_id: 2,
liked: [1],
content: “a”
}
]
The desired result is:
articles = [
{
_id: 1,
liked: [
{
_id: 1,
name: ‘a’,
email: ‘a.com’,
password: ‘a’
},
{
_id: 2,
name: ‘b’,
email: ‘b.com’,
password: ‘b’
}
],
content: “a&b”
},
{
_id: 2,
liked: [
{
_id: 1,
name: ‘a’,
email: ‘a.com’,
password: ‘a’
}
],
content: “a”
}
]
I tried to resolve this matter by using Model.find(query)
and Model.aggregate(pipeline)
but each of the two approaches had pros and cons and couldn’t reached the good result. Please give me an advice.
Based on what you have shared a simple $lookup
in an Model.aggregate() query would get you that output:
const articles = await Article.aggregate([
{
"$lookup": {
"from": "users",
"localField": "liked",
"foreignField": "_id",
"as": "liked"
}
}
]);
See HERE for a working example.
However, if you were to change your schema to use referenced docs then you could use populate to replace each _id
in the Article.liked
array with the corresponding User
document at the time of query retrieval. Either way will work.
This is how you would use populate:
const articleSchema = Schema({
liked: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'User' // create a reference to User
}],
content: String
})
then do
const articles = await Article.find().populate({path: 'liked', model: User});
Note: this example with populate()
works on the predicate that each User._id
field of each User
document is of the mongoose ObjectId
type.