我想填充子文档的字段,它是常见模式的可区分元素(
Notificationable
区分为Message
或FriendRequest
)。
这个问题与这个问题非常相似:mongoosejs: populated an array of objectId's from different schemas,这个问题两年前还没有解决。由于猫鼬进化了,鉴别器也进化了,我再次问这个问题。
到目前为止我尝试过的:
Notification.find({_id: 'whatever'})
.populate({
path: 'payload',
match: {type: 'Message'},
populate: ['author', 'messageThread']
})
.populate({
path: 'payload',
match: {type: 'FriendRequest'},
populate: ['to', 'from']
})
.exec();
这不起作用,因为路径是相同的。 所以我尝试了:
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();
这也不起作用,可能是因为匹配是在子文档中执行的,因此没有字段
type
。
这个问题有什么解决办法吗?
这是我的(主要)模型,我没有提供 User 或 MessageThread。
主要文档:
const NotificationSchema = new Schema({
title: String,
payload: {
type: Schema.Types.ObjectId,
ref: 'Notificationable'
});
mongoose.model('Notification', NotificationSchema);
有效负载父架构
let NotificationableSchema = new Schema(
{},
{discriminatorKey: 'type', timestamps: true}
);
mongoose.model('Notificationable', NotificationableSchema);
以及两种可区分的可能性:
let Message = new Schema({
author: {
type: Schema.Types.ObjectId,
ref: 'User'
},
messageThread: {
type: Schema.Types.ObjectId,
ref: 'MessageThread'
}
}
Notificationable.discriminator('Message', Message);
并且:
let FriendRequest = new Schema({
from: {
type: Schema.Types.ObjectId,
ref: 'User'
},
to: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}
Notificationable.discriminator('FriendRequest', FriendRequest);
我已经尝试过这个方法来解决我遇到的类似问题,我认为它可以帮助您解决问题
Notifiable.findOne({_id: 'whatever'})
.populate({
path: 'payload',
populate: { path: '__t' }, // Populating the discriminator key
model: function(doc) {
// Choose the appropriate discriminator model based on the value of the discriminator key
switch (doc.payload.__t) {
case 'Message':
return Message;
case 'FriendRequest':
return FriendRequest;
default:
throw new Error('Invalid discriminator value');
}
}
})
您还应该将模型导入到调用此代码片段的同一文件中,无论是控制器文件还是服务文件