Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reference Nest.js中的Mongoose子文档_Reference_Schema_Nestjs_Subdocument - Fatal编程技术网

Reference Nest.js中的Mongoose子文档

Reference Nest.js中的Mongoose子文档,reference,schema,nestjs,subdocument,Reference,Schema,Nestjs,Subdocument,我正在将我的应用程序从express.js移到Nest.js,如果不使用mongoose.Schema({…})声明模式的旧方法,我就找不到在另一个模式中引用一个mongoose模式的方法 让我们使用文档中的示例,这样我可以澄清我的问题: @Schema() 导出类Cat扩展文档{ @支柱( 名称:字符串; } export const CatSchema=SchemaFactory.createForClass(Cat); 现在,我想要的是这样的: @Schema() 导出类所有者扩展文档{

我正在将我的应用程序从express.js移到Nest.js,如果不使用mongoose.Schema({…})声明模式的旧方法,我就找不到在另一个模式中引用一个mongoose模式的方法

让我们使用文档中的示例,这样我可以澄清我的问题:

@Schema()
导出类Cat扩展文档{
@支柱(
名称:字符串;
}
export const CatSchema=SchemaFactory.createForClass(Cat);
现在,我想要的是这样的:

@Schema()
导出类所有者扩展文档{
@属性({type:[Cat],必需:true})
猫:猫[];
}
export const OwnerSchema=SchemaFactory.createForClass(所有者);
当我以这种方式定义模式时,会出现如下错误:模式配置无效:
Cat
不是有效的模式配置 在数组中键入
cats


那么,使用这种面向对象的方法来定义模式,在另一个模式中引用一个模式的正确方法是什么呢?

我深入研究了源代码,了解了SchemaFactory.createForClass方法如何转换模式类

那么它是如何工作的呢? 1.请看下面的示例:
@Schema()
导出类Cat扩展文档{
@支柱(
名称:字符串;
}
export const catSchema=SchemaFactory.createForClass(Cat);
基本上,当您执行
SchemaFactory.createForClass(Cat)

Nest将类语法转换为Mongoose模式语法,因此最终,转换的结果如下:

const schema=newmongoose.schema({
名称:{type:String}//请注意,'String'现在是大写的。
});
2.转换是如何工作的? 请查看此文件:

导出函数属性(选项?:属性选项):属性编辑器{
返回(目标:对象,属性key:string | symbol)=>{
options=(options |{})作为mongoose.SchemaTypeOpts;
const isRawDefinition=选项[原始对象定义];
如果(!options.type&&!Array.isArray(options)&!isRawDefinition){
const type=Reflect.getMetadata(type\u METADATA\u KEY、target、propertyKey);
if(类型===数组){
options.type=[];
}else if(type&&type!==对象){
options.type=类型;
}
}
TypeMetadataStorage.addPropertyMetadata({
target:target.constructor,
propertyKey:propertyKey作为字符串,
选项,
});
};
}
在这里,您可以看到
Prop()
decorator在幕后做了什么。 当您这样做时:

@Prop()
名称:字符串;
Prop
函数将被调用,在这种情况下不带参数

const type=Reflect.getMetadata(type\u METADATA\u KEY、target、propertyKey);
使用
Reflect
API,我们可以获得执行
name:string
操作时使用的数据类型。
type
变量的值现在设置为
String
。请注意,它不是
字符串
反射
API将始终返回数据类型的构造函数版本,因此:

  • number
    将被序列化为
    number
  • string
    将被序列化为
    string
  • boolean
    将被序列化为
    boolean
  • 等等
TypeMetadataStorage.addPropertyMetadata
然后将下面的对象存储到存储中

{
目标:用户,
propertyKey:'名称',
选项:{type:String}
}
让我们看一下:

导出类TypeMetadataStorage主机{
私有模式=新数组();
私有属性=新数组();
addPropertyMetadata(元数据:PropertyMetadata){
this.properties.push(元数据);
}
}
因此基本上,该对象将存储到
typeMetadataStorage主机
中的
properties
变量中。
TypeMetadataStorageHost
是一个将存储大量这些对象的单例

3.模式生成 要了解
SchemaFactory.createForClass(Cat)
如何生成Mongoose模式,请查看以下内容:

导出类SchemaFactory{
静态createForClass(目标:类型){
const schemaDefinition=DefinitionsFactory.createForClass(目标);
常量schemaMetadata=TypeMetadataStorage.getSchemaMetadataByTarget(
目标,,
);
返回新的mongoose.Schema(
方案定义,
schemaMetadata&&schemaMetadata.options,
);
}
}
最重要的部分是:
const schemaDefinition=DefinitionsFactory.createForClass(目标)。注意,这里的目标是您的
Cat

您可以在此处看到方法定义:

导出类定义工厂{
静态createForClass(目标:类型):mongoose.SchemaDefinition{
设schemaDefinition:mongoose.schemaDefinition={};
schemaMetadata.properties?.forEach((项)=>{
const options=this.inspectTypeDefinition(item.options,如有);
模式定义={
[item.propertyKey]:任何选项,
…方案定义,
};
});
返回模式定义;
}
schemaMetadata.properties
包含执行
TypeMetadataStorage.addPropertyMetadata
操作时存储的对象:

[
{
目标:用户,
propertyKey:'名称',
选项:{type:String}
}
]
forEach
将产生:

{
名称:{type:String}
}
最后,它将被用作
mongoose.Schema
构造函数的参数:

返回新的mongoose.Schema(
方案定义,
schemaMetadata&&schemaMetadata.options,
);
4.因此,要回答这个问题: 您应该将什么作为
Prop()
参数

还记得什么时候嵌套forEach来生成Mongoose模式吗

schemaMetadata.properties?.forEach((项)=>{
常量选项
import { Prop, raw, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Education } from '../../education/schemas';
import { RECORD_STATUS } from '../../common/common.constants';
import { Employment } from '../../employment/schemas';
import {
    JOB_SEARCH_STATUS,
    LANGUAGE_PROFICIENCY
} from '../user-profile.constants';

const externalLinks = {
    linkedInUrl: { type: String },
    githubUrl: { type: String },
    twitterUrl: { type: String },
    blogUrl: { type: String },
    websiteUrl: { type: String },
    stackoverflowUrl: { type: String }
};

const address = {
    line1: { type: String, required: true },
    line2: { type: String },
    zipCode: { type: String },
    cityId: { type: Number },
    countryId: { type: Number }
};

const language = {
    name: { type: String, require: true },
    code: { type: String, required: true },
    proficiency: { type: String, required: true, enum: LANGUAGE_PROFICIENCY }
};

const options = {
    timestamps: true,
};

export type UserProfileDocument = UserProfile & mongoose.Document;

@Schema(options)
export class UserProfile {

    _id: string;

    @Prop()
    firstName: string;

    @Prop()
    lastName: string;

    @Prop()
    headline: string;

    @Prop({
        unique: true,
        trim: true,
        lowercase: true
    })
    email: string;

    @Prop()
    phoneNumber: string

    @Prop(raw({
        jobSearchStatus: { type: String, enum: JOB_SEARCH_STATUS, required: true }
    }))
    jobPreferences: Record<string, any>;

    @Prop(raw(externalLinks))
    externalLinks: Record<string, any>;

    @Prop([String])
    skills: string[];

    @Prop(raw({ type: address, required: false }))
    address: Record<string, any>;

    @Prop()
    birthDate: Date;

    @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Employment' }] })
    employments: Employment[];

    @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Education' }] })
    educations: Education[];

    @Prop(raw([language]))
    languages: Record<string, any>[];

    @Prop()
    timeZone: string;

    @Prop()
    createdAt: Date;

    @Prop()
    updatedAt: Date;

    @Prop({
        enum: RECORD_STATUS,
        required: true,
        default: RECORD_STATUS.Active
    })
    recordStatus: string;
}

export const UserProfileSchema = SchemaFactory.createForClass(UserProfile);