我正在尝试为存储在子文档属性内的对象 ID 创建动态引用。该属性可以引用多个模型(甚至是在不同的猫鼬数据库实例中注册的模型),因此我直接使用模型实例而不是模型名称。
const subSchema = new Schema({
category: String,
ref: {
type: Schema.Types.ObjectId,
ref: function() {
return this.category === 'catA' ? CategoryAModel : CategoryBModel // imports model instances
}
}
})
const parentSchema = new Schema({
name: String,
children: [subSchema]
})
const ParentModel = db.model('Parent', parentSchema)
如您所见,
ref
属性是来自CategoryAModel
或CategoryBModel
的文档的对象ID。我开始为这个模型创建文档,如下所示:
const data = {
name: 'Test Data',
children: [
{
category: 'catA',
ref: '658e9f1901f3da2c14920401' // <- existing document from CategoryAModel
},
{
category: 'catB',
ref: '654995e0c89d1c19c84e77b7' // <- existing document from CategoryBModel
}
]
}
但是当我尝试
populate
时,ref
的 category: 'catA'
变为空(尽管存在)。我在 this
的 ref 函数中记录了 ref
上下文,发现 this
指的是正在处理的文档(与上面的数据形状相同),并且 this.category
是未定义的,因为它实际上位于 内部children
数组。本质上,使 ref
总是导致成为 CategoryBModel
既然是数组,那我该如何去动态引用呢?有没有办法访问所引用的
subSchema
的索引?
refPath
来代替。 Mongoose 设计了 populate
方法来使用 refPath
选项进行动态模型,并且将满足您的需求。
像这样使用它:
const subSchema = new Schema({
category: String,
ref: {
type: Schema.Types.ObjectId,
refPath: 'children.classifier', //< refPath should point to classifier
},
classifier: {
type: String,
enum: ['CategoryAModel', 'CategoryBModel'] //< The name of your models
}
})
现在,当您保存
Parent
文档时,children
对象应该将您想要填充的模型存储在该 classifier
字符串中。您的数据将如下所示:
const data = {
name: 'Test Data',
children: [
{
category: 'catA',
ref: ObjectId("658e9f1901f3da2c14920401"), // <- existing document from CategoryAModel
classifier: 'CategoryAModel'
},
{
category: 'catB',
ref: ObjectId("654995e0c89d1c19c84e77b7"), // <- existing document from CategoryBModel
classifier: 'CategoryBModel'
}
]
}
现在您可以像这样填充:
const parents = await ParentModel.find({}).populate("children.ref");