父文档数组内子文档的动态 ObjectID 引用

问题描述 投票:0回答:1

我正在尝试为存储在子文档属性内的对象 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
的索引?

javascript mongoose mongoose-schema mongoose-populate
1个回答
0
投票

您应该使用

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");
© www.soinside.com 2019 - 2024. All rights reserved.