You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:13:14