NestJS - 如何使用装饰器创建嵌套模式

问题描述 投票:0回答:7

假设我想用猫鼬构建以下模式:

const userSchema = new Schema({
  name: {
    firstName: String,
    lastName: String
  }
})

如何使用 NestJS 装饰器(

@Schema()
&
@Prop()
)做到这一点?

我尝试了这个方法,但没有成功:

@Schema()
class Name {
  @Prop()
  firstName: string;

  @Prop()
  lastName: string;
}

@Schema()
class User extends Document {
  @Prop({ type: Name })
  name: Name;
}

我也不想使用

raw()
方法。

mongoose schema nestjs mongoose-schema
7个回答
43
投票

这是我的方法,效果很好,并且不涉及删除@schema():

// Nested Schema
@Schema()
export class BodyApi extends Document {
  @Prop({ required: true })
  type: string;

  @Prop()
  content: string;
}
export const BodySchema = SchemaFactory.createForClass(BodyApi);

// Parent Schema
@Schema()
export class ChaptersApi extends Document {
  // Array example
  @Prop({ type: [BodySchema], default: [] })
  body: BodyContentInterface[];

  // Single example
  @Prop({ type: BodySchema })
  body: BodyContentInterface;
}
export const ChaptersSchema = SchemaFactory.createForClass(ChaptersApi);

当您在架构上设置该选项时,这将正确保存并显示时间戳


9
投票

我还没有发现NestJS的这一部分足够灵活。对我来说,一个可行的解决方案(经过测试)如下:

@Schema({_id: false}) // _id:false is optional
class Name {
  @Prop() // any options will be evaluated
  firstName: string; // data type will be checked

  @Prop()
  lastName: string;
}

@Schema()
class User {
  @Prop({type: Name}) // {type: Name} can be omitted
  name: Name;
}

以这种方式定义模式将使所有内容(类装饰器、传递选项、数据类型验证、NestJS 功能等)按预期工作。唯一的“问题”是将为每个

_id
创建
@Schema
属性,而您可能不希望这样,就像您的情况一样。您可以通过将
{_id: false}
作为选项对象添加到
@Schema()
来避免这种情况。请记住,任何进一步的嵌套模式都不会被阻止创建
_id
属性,例如

这个:

@Schema() // will create _id filed
class Father {
  age: number;
  name: string;
}

@Schema({_id: false}) // won't create _id field
class Parents {
  @Prop()
  father: Father;

  @Prop()
  mother: string;
}

@Schema()
class Person {
  @Prop()
  parents: Parents;
}

将产生这个:

{
  _id: ObjectId('someIdThatMongoGenerated'),
  parents: {
    father: {
      _id: ObjectId('someIdThatMongoGenerated'),
      age: 40,
      name: Jon Doe
    },
    mother: Jane Doe
  }
}

另一个解决方法是使用原生猫鼬在 NestJS 中创建模式,如下所示:

const UserSchema = new mongoose.Schema({
  name: {
    firstName: {
      type: String, // note uppercase
      required: true // optional
    },
    lastName: {
      type: String,
      required: true
    }
  }
});

6
投票

所做的更改:

  1. 子文档类没有
    @Schema
    装饰器
  2. 子文档类需要从
    Document
     扩展 
    'mongoose'

user.schema.ts

import { Document } from 'mongoose';

@Schema()
export class User extends Document {
  @Prop({ type: Name })
  name: Name;
}

export const UserSchema = SchemaFactory.createForClass(User);

name.schema.ts

import { Document } from 'mongoose';

export class Name extends Document {
  @Prop({ default: " " })
  firstName: string;

  @Prop({ default: " " })
  lastName: string;
}

2
投票

你也可以用这个。

    @Schema()
    class User extends Document {
      @Prop({ type:  { firstName: String, lastName: String })
      name: Name;
    }

2
投票

尝试从嵌套的“Name”中删除 @schema() 装饰器,仅将其保留在文档的根目录中。

还记得在根级别扩展“mongoose.Document”。

    import { Prop, Schema, SchemaFactory, } from '@nestjs/mongoose';
    import { Document  } from 'mongoose';
        
    class Name {
      @Prop()
      firstName: string;
    
      @Prop()
      lastName: string;
    }
    
    @Schema()
    class User extends Document {
      @Prop({ type: Name })
      name: Name;
    }
    export const userSchema = SchemaFactory.createForClass(user);

1
投票

顶级文档

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
import { FanNotification } from './notification.schema';

export type FanDocument = HydratedDocument<Fan>;

@Schema()
export class Fan {

  @Prop({ type: FanNotification, default: () => ({}) })
  notifications: FanNotification;

}

export const FanSchema = SchemaFactory.createForClass(Fan);

我使用

default: () => ({})
创建默认值。

嵌入式文档

import { Prop, Schema } from '@nestjs/mongoose';
import { AllMethod } from 'common/types';
import { Schema as MongooseSchema } from 'mongoose';

@Schema({ _id: false })
export class FanNotification {
  @Prop({
    type: MongooseSchema.Types.Mixed,
    default: { sms: true, email: true },
  })
  chat: AllMethod;

}

为了确保

@Prop()
被识别,并防止自动创建集合,我通过了
{ _id: false }


-5
投票

首先,对于这种情况,您应该使用猫鼬模式。简单明了:

export const UserSchema = new mongoose.Schema(
  {
    name: [UserNameSchema],
  },
  {
    timestamps: true,
  },
);

如果你不喜欢这种方法,你应该遵循官方文档:

@Prop(raw({
  firstName: { type: String },
  lastName: { type: String }
}))
details: Record<string, any>;
© www.soinside.com 2019 - 2024. All rights reserved.