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

NestJS嵌套对象Schema配置问题:GraphQL @Field装饰器异常解决

问题解决:NestJS中MongoDB嵌套对象结合GraphQL的字段处理

问题背景

MongoDB模型结构:

{
  ...
  settings: {
    positions: [
      {
       column: number,
       row: number,
       buttonId: (ref to Button model)
      }
    ]
  }
}

用户原NestJS Schema定义:

@Schema({ _id: false })
@ObjectType()
class Settings {
  @Field(() => [Object])
  @Prop({ type: [{ column: Number, row: Number, buttonId: String }] })
  positions: { column: number; row: number; buttonId: string };
}

const SettingsSchema = SchemaFactory.createForClass(Settings);

@Schema()
@ObjectType()
export class Keyboard {
  @Field(() => ID)
  _id: string;

  @Field(() => User)
  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User' })
  author: User;

  @Field(() => Group, { nullable: true })
  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'Group' })
  group?: Group;

  @Field(() => Settings, { nullable: true })
  @Prop({ type: SettingsSchema })
  settings?: Settings;
}

export const KeyboardSchema = SchemaFactory.createForClass(Keyboard);

出现的错误:

Cannot determine GraphQL output type for 'positions' of 'Settings' class. Make sure your class is decorated with an appropriate decorator.

解决方案

问题核心是Settings类的positions字段用了[Object]作为GraphQL类型,GraphQL无法识别匿名对象结构。需为数组内的子对象单独定义类型:

  1. 定义Position子对象的Schema和GraphQL类型
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { ObjectType, Field, ID } from '@nestjs/graphql';

@Schema({ _id: false })
@ObjectType()
class Position {
  @Field(() => Number)
  @Prop({ type: Number, required: true })
  column: number;

  @Field(() => Number)
  @Prop({ type: Number, required: true })
  row: number;

  @Field(() => ID)
  @Prop({ type: Schema.Types.ObjectId, ref: 'Button', required: true })
  buttonId: string;
}

const PositionSchema = SchemaFactory.createForClass(Position);
  1. 修改Settings类,使用明确的Position类型
@Schema({ _id: false })
@ObjectType()
class Settings {
  @Field(() => [Position])
  @Prop({ type: [PositionSchema], default: [] })
  positions: Position[];
}

const SettingsSchema = SchemaFactory.createForClass(Settings);
  1. Keyboard类保持原有定义即可
@Schema()
@ObjectType()
export class Keyboard {
  @Field(() => ID)
  _id: string;

  @Field(() => User)
  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User' })
  author: User;

  @Field(() => Group, { nullable: true })
  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'Group' })
  group?: Group;

  @Field(() => Settings, { nullable: true })
  @Prop({ type: SettingsSchema })
  settings?: Settings;
}

export const KeyboardSchema = SchemaFactory.createForClass(Keyboard);

关键说明

  • GraphQL要求明确的类型定义,不能用匿名Object作为字段类型,必须为每个嵌套对象添加@ObjectType()装饰器
  • Mongoose嵌套数组字段直接引用子对象Schema即可,SchemaFactory会自动处理结构映射
  • 若buttonId是Button模型的引用,需在Prop中指定ref: 'Button',同时GraphQL字段用ID类型对应

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:55:25