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

rjzwgtxy  于 2023-01-05  发布在  Go
关注(0)|答案(7)|浏览(184)

假设我想用mongoose构建下面的模式:

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()方法。

q9rjltbz

q9rjltbz1#

下面是我的方法,它工作得很好,而且不涉及删除@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);

当您在方案中设置了该选项时,这将正确保存并显示时间戳

0qx6xfy6

0qx6xfy62#

所做变更:
1.子文档类没有@Schema装饰器
1.子单据类需要从'mongoose'扩展Document
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;
}
oyjwcjzk

oyjwcjzk3#

我还没有发现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功能等)按预期工作。唯一的"问题"是将为每个@Schema创建_id属性,而您可能不希望这样,您可以通过将{_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
  }
}

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

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

ego6inou4#

你也可以用这个。

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

k0pti3hp5#

尝试从嵌套的“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);
qaxu7uf2

qaxu7uf26#

顶级文档

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 }

6ss1mwsb

6ss1mwsb7#

首先,你应该使用mongoose模式来处理这个问题,它很简单明了:

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

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

@Prop(raw({
  firstName: { type: String },
  lastName: { type: String }
}))
details: Record<string, any>;

相关问题