mongoose: Populating a discriminated subdocument - node.js

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

Related

How can I search through mongoose schema object? [duplicate]

This question already has answers here:
How to query nested objects?
(3 answers)
Closed 3 years ago.
I am trying to search through all the comments and return all comments created by a specific user from my mongodb how ever when i try to search the array returned is empty.
I have tried :
Comment.find({author: {$elemMatch: {username: req.params.username}}}, (err, foundComments) => {
// Code goes here
});
The Mongoose Comment Schema:
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
text: String,
discussion:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
}],
createdAt: {
type: Date,
default: Date.now,
},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
username: 'String',
avatar: {
image: String,
imageId: String,
},
},
likes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
}],
dislikes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
}],
});
module.exports = mongoose.model('Comment', commentSchema);
When I run it I am expecting foundComments to be an array [ array of comments ] but I just get an empty array [].
Comment.find({"author.username":req.params.username});
Comment.find({"username": req.params.username},{"discussion":1,"_id":0})

Populate inside JSON object Mongoose

i want to populate inside JSON object, but it doesnt work. Here is the code. The response i still get is the objectId when i log the response of the Group variable
population
var Groups = await GroupModel.find({ownerUser : user.battletag}).populate([
{
path: "selectedInstance",
model: "Instances"
},
{
path: "createdAs",
model: "Characters",
populate: {
path: "race",
model: "Races"
}
},
{
path: "characters",
populate: {
path: "character",
model: "Characters"
}
}
]).exec();
schema
var GroupSchema = new Schema({
createdAs: {type: Schema.Types.ObjectId, ref: 'Characters'},
description: String,
minimumItemLevel: Number,
voiceChat: String,
completedAchievements: [{ type: Schema.Types.ObjectId, ref: 'Achievements' }],
selectedInstance: { type: Schema.Types.ObjectId, ref: 'Instances' },
instanceDifficulty: String,
private: Boolean,
characters: [{character: { type: Schema.Types.ObjectId, ref: 'Characters' }, role: String}],
queue: [{ type: Schema.Types.ObjectId, ref: 'Characters' }],
ownerUser: String,
groupSignature: String,
status: {type: String, default: "Open"},
maxPlayers: Number,
minPlayers: Number,
expansion: String,
createDate: {type: Date, default: Date.now}
});
I have found the solution for the problem, now it works!
var Groups = await GroupModel.find({ownerUser : user.battletag}).populate([
{
path: "selectedInstance",
model: "Instances"
},
{
path: "createdAs",
model: "Characters",
populate: {
path: "race",
model: "Races"
}
},
{
path: "characters.character",
model: "Characters"
}
]).exec();
return Groups

how to populate embed array of object in mongoose

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

How to populate nested entities in mongoose?

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

Mongoose query to multiple values

So I have a Mongoose query question that I can't seem to figure out. I'm trying to query a schema to find all documents in the collection that have a parameter specified user id in one of a few places... What I have so far is this:
Schema:
var Module = new Schema({
template: { type: Schema.ObjectId, ref: 'template' },
owner: { type: String, required: true, index: { unique: false } },
primary: { type: Schema.ObjectId, ref: 'User' },
users: [{ type: Schema.ObjectId, ref: 'User' }],
data: [],
children: [{ type: Schema.ObjectId, ref: 'Module' }],
parent: { type: Schema.ObjectId, ref: 'Module' }
});
Query:
Module.find()
.or([{owner: req.user.id}, {primary: req.user.id}])
.populate('primary users children parent template')
.exec(function (err, modules) {
...
}
So as of now, it seems to correctly find documents that have the req.user.id as the primary or owner field, but how would I also return all documents where the users array is also searched for this value?
Thanks!

Resources