Mongoose如何populate关联集合中非独立模型的嵌套对象字段
结论
完全可以通过Mongoose原生populate方法实现该需求,不需要将test集合下的嵌套clinicalCase子文档注册为独立模型。
实现方案
Mongoose原生支持跨集合填充父文档内的嵌套数组子文档,只需要在填充时正确指定关联规则即可,有两种可选的配置方式:
方式1:查询时直接配置populate规则(无需修改现有Schema)
直接在查询Question集合时传入完整的populate配置,不需要改动已有的Schema定义,示例代码如下:
// 查询题目列表并填充关联的clinicalCase子文档 const questionList = await Question.find().populate({ path: "clinicalCase", // 要填充的当前文档字段 model: "Test", // 关联的父集合对应的模型名 localField: "clinicalCase", // 当前Question文档用于关联匹配的字段 foreignField: "clinicalCase._id", // Test集合中用于匹配的嵌套子文档_id路径 justOne: true // 只返回匹配到的单个子文档,而非整个Test文档 });
执行上述查询后,返回的question文档中clinicalCase字段会被直接替换为Test集合下对应_id的子文档,结构示例:
{ _id: "xxx", questionString: "题目内容", test: "xxx", clinicalCase: { _id: "匹配到的子文档id", text: "对应临床案例内容" } // 其余字段... }
方式2:在Schema中预配置关联规则
如果需要在多个查询场景下复用该填充逻辑,可以直接在questionSchema的clinicalCase字段中预定义关联配置,后续查询时只需要指定populate路径即可:
- 首先修改
questionSchema定义:
const questionSchema = new mongoose.Schema({ test: { type: mongoose.Schema.Types.ObjectId, ref: "Test", }, questionString: { type: String, required: [true, "la question est obligatoire"], }, explanation: String, options: [option], tag: { type: mongoose.Schema.Types.ObjectId, ref: "Tag", }, clinicalCase: { type: mongoose.Schema.Types.ObjectId, ref: "Test", localField: "clinicalCase", foreignField: "clinicalCase._id", justOne: true } });
- 后续查询时直接传入路径即可完成填充:
const questionList = await Question.find().populate("clinicalCase");
注意事项
- 当前定义的
testSchema中已经为嵌套clinicalCase子文档配置了_id自动生成,满足关联匹配的前提要求,不需要额外调整。 - 如果使用Mongoose 5.x版本,建议升级到5.12及以上,低版本对嵌套子文档populate的支持存在已知兼容问题;Mongoose 6.x、7.x版本可直接使用上述配置。
- 如果需要过滤返回的子文档字段,可以在populate配置中增加
select参数,例如select: "text"就只会返回子文档的text字段。
内容的提问来源于stack exchange,提问作者Redouan AF
相关产品推荐
相关产品推荐

