假设我想用猫鼬构建以下模式:
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()
方法。
这是我的方法,效果很好,并且不涉及删除@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);
当您在架构上设置该选项时,这将正确保存并显示时间戳
我还没有发现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
}
}
});
所做的更改:
@Schema
装饰器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;
}
你也可以用这个。
@Schema()
class User extends Document {
@Prop({ type: { firstName: String, lastName: String })
name: Name;
}
尝试从嵌套的“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);
顶级文档
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 }
。
首先,对于这种情况,您应该使用猫鼬模式。简单明了:
export const UserSchema = new mongoose.Schema(
{
name: [UserNameSchema],
},
{
timestamps: true,
},
);
如果你不喜欢这种方法,你应该遵循官方文档:
@Prop(raw({
firstName: { type: String },
lastName: { type: String }
}))
details: Record<string, any>;