I have the following mongoose schema structure
userSchema = new Schema({
roles: [
role: {type: Schema.Types.ObjectId, ref: 'Role' }
]
})
rolesSchema = new Schema({
name: String,
roleEntities: [
{
entity : {type: Schema.Types.ObjectId, ref: 'RoleEntity' },
abilities : [{type: Schema.Types.ObjectId, ref: 'Ability' }]
}
]
}
roleEntitiesSchema = new Schema({
name: String
})
abilitiesSchema = new Schema({
name: String
})
How can i populate all these nested documents while doing a find on the USER model?
I tried using populate as below
User.find(ctx.request.query).populate(
{path: 'roles.role'
,populate: { path: 'roleEntities.entity'}
}).
exec()
but it's not resolving roleEntities.entity
Here's an extreme example of a deep populate nested inside of multiple objects/arrays:
Deal.find()
.populate({
path: 'fund',
populate: [{
path: 'organizer',
populate: {
path: 'banking.accounts.transactions.associatedInvestment',
model: 'Investment'
}
}, {
path: 'documents'
}]
})
You can try chaining populate operations
User.find()
.populate("roles.role")
.populate("roles.role.roleEntities.entity")
Mongoose 4 :
User
.find()
.populate({
path: 'roleIds',
model: 'roles',
populate: {
path: 'otherIds',
model: 'other'
}
})
for me worked the following
.populate({
path: 'favorites.favorite',
model: 'Joke',
populate: {
path: 'user',
model: 'User',
},
Related
In my blog model;
...
user: {
type: mongoose.Types.ObjectId,
ref: 'users',
required: true,
},
...
And this is my user model;
follower: [
{
type: mongoose.Types.ObjectId,
ref: 'users'
}
],
So I'm gettting data like this;
const Post = await Blog.findOne({slug: post}).populate({
path: 'user',
select: 'name image count(follower)'
})
Of course count(follower) not working. I want to get followers count, how can I do that?
On the main page, there is a hyperlink with profile/5aa3cfb783622a145a86d616 that points to the profile page of a user, where 5aa3cfb783622a145a86d616 is the Object ID of the user (it is shown as "_id" : ObjectId("5aa3cfb783622a145a86d616") in MongoDB).
When I click on the link, the page fully loads without any problem. However, the terminal still says Cast to ObjectId failed for value "..." at path "_id" for model "User", and the browser's favicon still shows that it is loading, even though the page has fully loaded.
I tried searching for answers, but none of them are specific to my problem.
EDIT
After playing with the code, I found that the problem seems to lie in the multiple "populate" methods, which I have previously ignored when simplifying the questions, as I thought there was no issue with it. I now include the full code below.
Inside the User document, there is a Post array containing the Post's ID. Each post document has Author, Likes, and Comment. In the Comment array, each comment document has the Author's ID. All of these have to be populated.
NodeJS/Mongoose:
router.get("/:id", function(req, res){
User.findById(req.params.id).populate({
path: 'posts',
populate: [{
path: 'author',
},
{
path: 'likes',
},
{
path: 'comments',
populate: [{
path: 'author'
}]
}]
})
.exec(function(err, user){
console.log(user);
res.render("profile", {user: user});
});
});
User Schema
var UserSchema = new mongoose.Schema({
posts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Post"
}
]
});
Post Schema
var postSchema = mongoose.Schema({
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
],
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
Comment Schema
var commentSchema = mongoose.Schema({
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
});
When I console.log(user), the terminal returns the following. I'm not too sure why it shows author[object] instead of its actual ID, maybe this is the problem?
{ posts:
[ { likes: [],
comments: [],
_id: 5aa3d0d806711d1483ae7e3e,
__v: 0,
author: [Object] },
{ likes: [],
comments: [],
_id: 5aa3cfc483622a145a86d618,
__v: 0,
author: [Object] },
{ likes: [],
comments: [],
_id: 5aa3cfbe83622a145a86d617,
__v: 0,
author: [Object] } ],
__v: 3}
EDIT 2
Weird enough, my other route which has the same structure (except its friendPosts) is working without any issue.
router.get("/home", function(req, res){
User
.findById(req.user._id)
.populate({
path: 'friendPosts',
populate: [{
path: 'author',
},
{
path: 'likes',
},
{
path: 'comments',
populate: [{
path: 'author'
}]
}]
})
.exec(function(err, currentUser){
res.render("main/home", {user: currentUser});
});
});
You need to try this:
const { ObjectId } = require('mongoose').Types;
router.get("/:id", function(req, res) {
const { id } = req.params;
User.findOne({ id: ObjectId(id)}).populate({
path: 'posts',
populate: [{
path: 'author',
},
{
path: 'likes',
},
{
path: 'comments',
populate: [{
path: 'author'
}]
}
]
}).exec(function(err, user) {
console.log(user);
res.render("profile");
});
});
I want to populate the fields of a subdocument, which is a discriminated element of a common Schema (Notificationable discriminated into Message or FriendRequest).
This question is quite similar to this one: mongoosejs: populating an array of objectId's from different schemas, which was not solved two years ago. Since mongoose evolved, and discriminator also, I am asking the question again.
What I have tried so far:
Notification.find({_id: 'whatever'})
.populate({
path: 'payload',
match: {type: 'Message'},
populate: ['author', 'messageThread']
})
.populate({
path: 'payload',
match: {type: 'FriendRequest'},
populate: ['to', 'from']
})
.exec();
This does not work, because the path is the same.
So I tried:
Notification.find({_id: 'whatever'})
.populate({
path: 'payload',
populate: [
{
path: 'messageThread',
match: {type: 'Message'},
},
{
path: 'author',
match: {type: 'Message'},
},
{
path: 'from',
match: {type: 'FriendRequest'},
},
{
path: 'to',
match: {type: 'FriendRequest'},
},
]
})
.exec();
Which does not work either, maybe because the match is executed in the subdocument and thus does not have a field type.
Is there any solution for this?
Here are my (main) models, I did not provide User or MessageThread.
The main document:
const NotificationSchema = new Schema({
title: String,
payload: {
type: Schema.Types.ObjectId,
ref: 'Notificationable'
});
mongoose.model('Notification', NotificationSchema);
The payload Parent schema
let NotificationableSchema = new Schema(
{},
{discriminatorKey: 'type', timestamps: true}
);
mongoose.model('Notificationable', NotificationableSchema);
And the two discriminated possibilities:
let Message = new Schema({
author: {
type: Schema.Types.ObjectId,
ref: 'User'
},
messageThread: {
type: Schema.Types.ObjectId,
ref: 'MessageThread'
}
}
Notificationable.discriminator('Message', Message);
And:
let FriendRequest = new Schema({
from: {
type: Schema.Types.ObjectId,
ref: 'User'
},
to: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}
Notificationable.discriminator('FriendRequest', FriendRequest);
I Have following model for a team
var team = new mongoose.Schema({
supervisor: { type: mongoose.Schema.Types.ObjectId, ref: 'employee' }, // SupervisorId
commanders: [{
employee: { type: mongoose.Schema.Types.ObjectId, ref: 'employee' }, //under supervisor
level: { type: Number, defult: 1 }
}]
});
while fetching data from DB I am able to populate supervisor but not employees in commanders array
I tried something like below
db.team.findOne({
supervisor: employeeId
}).populate({
path: 'supervisor',
populate: {
path: 'commanders',
populate: {
path: 'employee',
model
}
}
})
Need help.!!
Try with This:
db.team.findOne({
supervisor: employeeId
}).populate('supervisor commanders.employee')
I have the following schemas:
var userSchema = new Schema({
username: String,
rooms: [{type: Schema.Types.ObjectId, ref: 'Room'}]
});
var roomSchema = new Schema({
members: [
{
user:{type:Schema.Types.ObjectId, ref 'User'},
role: String
}
],
messages: [
{
text: String,
meta: {
send: {type: Schema.Types.ObjectId, ref 'User'},
sent_time: Date
}
}
]
});
I wish to obtain all rooms of a particular user and deep populate each room to get populated messages and members arrays so that each sender in a message is populated with username and each member is populated with his/her username, something like this:
User.findById(id).
populate({
path: 'rooms',
populate: [
{
path: 'members.user',
select: 'username'
},
{
path: 'messages.meta.sender',
select: 'username'
}
]
}).exec(function(err, self) { // self becomes deep populated});
Obviously, the above didn't work for me.