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

NestJS中Mongoose不对嵌套数组执行校验的问题

Mongoose嵌套子文档校验失效问题解决

问题场景

我定义了如下嵌套用户Schema:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { User } from 'src/users/schemas/user.schema';

@Schema({ _id: false })
export class NestedUser {
  @Prop({ required: true, type: mongoose.Schema.Types.ObjectId, ref: 'User' })
  userId: User;

  @Prop({ required: true })
  name: string;

  @Prop({ required: true })
  email: string;

  @Prop({ required: false, default: '' })
  imageUrl: string;
}

export const NestedUserSchema = SchemaFactory.createForClass(NestedUser);

同时定义了包含NestedUser数组的角色Schema:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { NestedUser, NestedUserSchema } from './nested-user.schema';
import { NestedTemplate, NestedTemplateSchema } from './nested-template.schema';

export type RoleDocument = mongoose.HydratedDocument<Role>;

@Schema()
export class Role {
  @Prop({ required: true })
  name: string;

  @Prop({ required: true, type: [NestedTemplateSchema], default: [] })
  templates: NestedTemplate[];

  @Prop({
    required: true,
    type: [NestedUserSchema],
    default: [],
  })
  users: NestedUser[];
}

export const RoleSchema = SchemaFactory.createForClass(Role);

但插入包含空字段的嵌套用户数据时,子文档未经过校验就被成功插入:

{
   "userId": "",
   "name": "",
   "imageUrl": "",
   "email": ""
}

问题原因

  1. required: true的局限性:Mongoose中required: true仅保证字段存在,对于字符串类型,空字符串''属于合法值,不会被拦截。
  2. ObjectId类型未做有效性校验:空字符串不是有效的MongoDB ObjectId,但Mongoose默认不会自动校验ObjectId格式,仅校验字段是否存在。
  3. 子文档数组校验未完全触发:父Schema中数组类型的子文档,默认可能未强制触发每个子项的完整校验规则。

解决方案

1. 增强NestedUser的字段校验

给每个必填字段添加更严格的校验规则,确保内容合法:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { User } from 'src/users/schemas/user.schema';

@Schema({ _id: false })
export class NestedUser {
  @Prop({ 
    required: true, 
    type: mongoose.Schema.Types.ObjectId, 
    ref: 'User',
    // 校验是否为有效ObjectId
    validate: {
      validator: (val: string) => mongoose.Types.ObjectId.isValid(val),
      message: 'userId必须是有效的MongoDB ObjectId'
    }
  })
  userId: User;

  @Prop({ 
    required: true,
    // 确保名称非空
    minlength: 1,
    message: 'name不能为空'
  })
  name: string;

  @Prop({ 
    required: true,
    // 确保邮箱非空且格式合法
    minlength: 1,
    match: /^\S+@\S+\.\S+$/,
    message: '邮箱格式不正确或不能为空'
  })
  email: string;

  @Prop({ required: false, default: '' })
  imageUrl: string;
}

export const NestedUserSchema = SchemaFactory.createForClass(NestedUser);

2. 开启父Schema的严格模式并增强数组校验

给Role Schema开启严格模式,同时给users数组添加校验,确保每个子项都符合规则:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { NestedUser, NestedUserSchema } from './nested-user.schema';
import { NestedTemplate, NestedTemplateSchema } from './nested-template.schema';

export type RoleDocument = mongoose.HydratedDocument<Role>;

// 开启严格模式,禁止插入Schema未定义的字段,增强校验严谨性
@Schema({ strict: 'throw' })
export class Role {
  @Prop({ required: true })
  name: string;

  @Prop({ required: true, type: [NestedTemplateSchema], default: [] })
  templates: NestedTemplate[];

  @Prop({
    required: true,
    type: [NestedUserSchema],
    default: [],
    // 校验数组中每个用户子文档的合法性
    validate: {
      validator: (users: NestedUser[]) => {
        return users.every(user => {
          return mongoose.Types.ObjectId.isValid(user.userId) && 
                 user.name.trim() !== '' && 
                 /^\S+@\S+\.\S+$/.test(user.email);
        });
      },
      message: '用户列表中存在无效的子文档'
    }
  })
  users: NestedUser[];
}

export const RoleSchema = SchemaFactory.createForClass(Role);

3. 插入/更新时强制触发校验

在执行数据库操作时,添加runValidators: true选项,强制Mongoose触发所有校验规则:

// 创建Role文档时开启校验
const role = new RoleModel(roleData);
await role.save({ runValidators: true });

// 更新时开启校验
await RoleModel.findByIdAndUpdate(roleId, updateData, { runValidators: true, new: true });

内容的提问来源于stack exchange,提问作者Abd al rahman shebani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 16:47:46