NestJs-Mongoose虚拟填充报错:虚拟名称触发TypeError问题排查
Mongoose虚拟填充嵌套字段报错解决
环境版本
- mongoose: ^6.6.2
- @nestjs/mongoose: ^9.2.0
现有模型代码
export class FormNotificationsLayout { @Prop() public logo?: string; } export class FormNotifications { @Prop() public layout?: FormNotificationsLayout; } @Schema({ toJSON: { virtuals: true }, toObject: { virtuals: true } }) export class Form { @Prop({ required: true }) public notifications: FormNotifications; }
需求
将form.notifications.layout.logo存储为UUID,查询Form时自动填充另一个集合中的File文档(不想使用File的MongoDB _id,因此无法直接用ref关联填充)。
尝试实现代码
虚拟填充定义
export const FormSchema = SchemaFactory.createForClass(Form).virtual( 'logoFile', { ref: 'File', foreignField: 'uuid', localField: 'notifications.layout.logo', }, );
查询代码
const entity = await this._repository .findOne({ id }) .populate('logoFile');
报错信息
TypeError: Invalid schema configuration: `LogoFile` is not a valid type at path `path`. See https://mongoosejs.com/docs/guide.html#definition for a list of valid schema types.
问题根源与解决方法
这个错误是因为NestJS的SchemaFactory.createForClass处理嵌套类时,会自动将嵌套类名首字母大写作为类型标识,而链式调用.virtual()时,Mongoose会误把虚拟字段名的首字母大写版本(LogoFile)当成了嵌套类型,触发了无效类型校验。
解决方式很简单,拆分Schema创建和虚拟字段定义的步骤:
// 先创建Form的Schema实例 export const FormSchema = SchemaFactory.createForClass(Form); // 单独定义虚拟填充 FormSchema.virtual('logoFile', { ref: 'File', foreignField: 'uuid', localField: 'notifications.layout.logo', });
额外注意事项:
- 确保
File集合的Schema中存在uuid字段,且该字段的值与Form的notifications.layout.logo存储的UUID完全一致 - 虚拟填充的
localField路径要准确对应嵌套字段的层级(这里notifications.layout.logo是正确的)
修改后再执行populate('logoFile'),就能正常填充关联的File文档了。
内容的提问来源于stack exchange,提问作者Ulys CHAMBARD
相关产品推荐
相关产品推荐

