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

使用TypeScript装饰器定义嵌套对象GraphQL Schema及报错解决

问题描述

需要为如下JSON结构编写TypeScript嵌套对象Schema:

{
   "firstname": "Jhon",
   "lastname": "Doe",
   "adress": {
      "street": "Park Avenue",
      "city": "New York",
      "zipcode": "97000"
   },
   "active": true
}

尝试使用TypeScript装饰器(结合NestJS + Mongoose + GraphQL)实现,定义User类后添加Adress嵌套类,执行时触发错误:

Error: Schema must contain uniquely named types but contains multiple types named "Adress".

尝试的错误代码

User类

@Schema({ timestamps: true })
@ObjectType()
export class User {
  @Field(() => String)
  _id: MongooseSchema.Types.ObjectId;

  @Prop({ type: String, required: true })
  @Field(() => String, { description: 'First Name' })
  firstname: string;

  @Prop({ type: String, required: true })
  @Field(() => String, { description: 'Last Name' })
  lastname: string;

  // 错误的地址对象引用
  @Prop({ type: Adress })
  @Field(() => Adress, { description: 'User Address' })
  adores: Adress;

  @Prop({ type: Boolean, default: true })
  @Field(() => Boolean, { description: 'User status' })
  active: boolean;
}

export const UserSchema = SchemaFactory.createForClass(User);

Adress类

@Schema({ _id: false })
@ObjectType()
export class Adress {
  @Prop({ type: String })
  @Field(() => String, { nullable: true, description: 'Street' })
  street?: string;

  @Prop({ type: String })
  @Field(() => String, { nullable: true, description: 'City' })
  city?: string;

  @Prop({ type: String })
  @Field(() => String, { nullable: true, description: 'Zip Code' })
  zipcode?: string;
}
问题原因
  • Mongoose嵌套Schema引用错误:在@Prop装饰器中直接传入Adress类是错误的,Mongoose需要的是子Schema实例,而非类本身。
  • 拼写不一致:User类中属性名写成了adores(应为address),虽不是直接报错原因,但会导致字段不匹配。
  • GraphQL类型重复:如果Adress类被重复定义或在多模块重复导入,会导致@ObjectType生成重复的GraphQL类型名称,触发报错。
正确实现方案

步骤1:定义并导出嵌套地址Schema

import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { ObjectType, Field } from '@nestjs/graphql';

@Schema({ _id: false }) // 禁用子文档自动生成_id
@ObjectType()
export class Address { // 统一拼写为Address,避免混淆
  @Prop({ type: String })
  @Field(() => String, { nullable: true, description: 'Street' })
  street?: string;

  @Prop({ type: String })
  @Field(() => String, { nullable: true, description: 'City' })
  city?: string;

  @Prop({ type: String })
  @Field(() => String, { nullable: true, description: 'Zip Code' })
  zipcode?: string;
}

// 生成Address对应的Mongoose Schema实例
export const AddressSchema = SchemaFactory.createForClass(Address);

步骤2:在User类中正确引用嵌套Schema

import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { ObjectType, Field } from '@nestjs/graphql';
import { Address, AddressSchema } from './address.entity'; // 统一导入地址类和Schema

@Schema({ timestamps: true })
@ObjectType()
export class User {
  @Field(() => String)
  _id: MongooseSchema.Types.ObjectId;

  @Prop({ type: String, required: true })
  @Field(() => String, { description: 'First Name' })
  firstname: string;

  @Prop({ type: String, required: true })
  @Field(() => String, { description: 'Last Name' })
  lastname: string;

  // 正确引用嵌套的Address Schema
  @Prop({ type: AddressSchema })
  @Field(() => Address, { description: 'User Address' })
  address: Address; // 修正属性名为address

  @Prop({ type: Boolean, default: true })
  @Field(() => Boolean, { description: 'User status' })
  active: boolean;
}

export const UserSchema = SchemaFactory.createForClass(User);

简化写法(无需单独导出AddressSchema)

如果不需要单独使用AddressSchema,可以直接在@Prop中生成:

@Prop({ type: SchemaFactory.createForClass(Address) })
@Field(() => Address, { description: 'User Address' })
address: Address;

内容的提问来源于stack exchange,提问作者Pillo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 16:07:53