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