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

Sin*_*dro 9 mongoose mongodb mongoose-schema nestjs

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

const userSchema = new Schema({
  name: {
    firstName: String,
    lastName: String
  }
})
Run Code Online (Sandbox Code Playgroud)

如何使用 NestJS 装饰器 ( @Schema()& @Prop()) 来实现?

我尝试这种方法,但没有运气:

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

  @Prop()
  lastName: string;
}

@Schema()
class User extends Document {
  @Prop({ type: Name })
  name: Name;
}
Run Code Online (Sandbox Code Playgroud)

我也不想使用该raw()方法。

aus*_*per 15

这是我的方法,效果很好,并且不涉及删除 @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);
Run Code Online (Sandbox Code Playgroud)

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

  • 它会创建 2 个单独的集合吗?我想要一个单一的集合。 (3认同)
  • @AnkitTanna不,只会创建您传递给模块中的“MongooseModule.forFeature”的模式。 (3认同)
  • BodyContentInterface 应该与 BodyApi 相同吗?它没有在任何地方定义 (2认同)
  • @AlexanderK1987,你不需要将它传递给 MongooseModule,我犯了同样的错误,一旦我删除它们,这些集合就再也没有回来。我想您必须坚持在自己的模块内使用这些模型,这是一个很好的做法。 (2认同)

And*_*rov 14

我还没有发现 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;
}
Run Code Online (Sandbox Code Playgroud)

以这种方式定义模式将使所有内容(类装饰器、传递选项、数据类型验证、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;
}
Run Code Online (Sandbox Code Playgroud)

将产生这个:

{
  _id: ObjectId('someIdThatMongoGenerated'),
  parents: {
    father: {
      _id: ObjectId('someIdThatMongoGenerated'),
      age: 40,
      name: Jon Doe
    },
    mother: Jane Doe
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Sam*_*waj 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);

Run Code Online (Sandbox Code Playgroud)

name.schema.ts

import { Document } from 'mongoose';

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

  @Prop({ default: " " })
  lastName: string;
}
Run Code Online (Sandbox Code Playgroud)