NestJS MongoDB 嵌套对象模式

3

我目前正在运行以下代码:

export class SystemInformationContent {
  createdAt: number;

  createdBy: User | mongoose.Schema.Types.ObjectId | null;

  updatedAt?: number;

  updatedBy?: User | mongoose.Schema.Types.ObjectId | null;
}

@Schema()
export class SystemInformation {
  @Prop(
    raw({
      createdAt: { type: Number, required: true },
      createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
      updatedAt: { type: Number, default: 0 },
      updatedBy: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        default: null,
      },
    }),
  )
  system: SystemInformationContent;
}

我没有找到任何“扩展” SystemInformationContent 模式的方法,因此在 @Prop() 装饰器中使用了 raw() 函数,但我想知道是否有一种类似于这样的方法:

export class SystemInformationContent {
  @Prop({ required: true })
  createdAt: number;

  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User' })
  createdBy: User | mongoose.Schema.Types.ObjectId | null;

  @Prop({ default: 0 })
  updatedAt?: number;

  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User', default: null })
  updatedBy?: User | mongoose.Schema.Types.ObjectId | null;
}

@Schema()
export class SystemInformation {
  @Prop(???)
  system: SystemInformationContent;
}

我没有找到任何有效的方法来将考虑 SystemInformationContent 模式的内容放入 SystemInformation.system @Prop() 中。
你们知道除了 raw 之外还有其他方法吗?或者我有什么遗漏吗?
编辑:我的 NestJS 应用程序中的所有类都在扩展 SystemInformation,因此它们都如下所示:
{
  ...,
  system: {
    createdAt: 1616778310610,
    createdBy: "605e14469d860eb1f0641cad",
    editedAt: 0,
    createdBy: null,
  },
}
3个回答

6

找到了解决方案!

我编辑了 SystemInformationContent 为:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { User } from '~/schemas/user.schema';

@Schema({ _id: false })
export class SystemInformationContent {
  @Prop({ type: Number, required: true })
  createdAt: number;

  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User' })
  createdBy: User;

  @Prop({ type: Number, default: 0 })
  updatedAt?: number;

  @Prop({
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    default: null,
  })
  updatedBy?: User;
}

export const SystemInformationContentSchema = SchemaFactory.createForClass(
  SystemInformationContent,
);

然后在SystemInformation中进行了编辑:

import { Prop, Schema } from '@nestjs/mongoose';
import {
  SystemInformationContent,
  SystemInformationContentSchema,
} from '~/schemas/systemInformationContent.schema';

@Schema()
export default class SystemInformation {
  @Prop({ required: true, type: SystemInformationContentSchema })
  system: SystemInformationContent;
}

现在一切都正常工作了,我使用了@Schema({ _id: false })来删除由SchemaFactory生成的ID,以便最终在数据库中得到以下结果:

{
  ...,
  "system": {
    "updatedBy": null,
    "updatedAt": 0,
    "createdAt": 1616847116986,
    "createdBy": {
      "$oid": "605f210cc9fe3bcbdf01c95d"
    }
  },
  ...,
}

0
如果您正在使用 typegoose (7.0 或更高版本),那么您当前的设置应该已经足够了,如果您在 tsconfig 中启用了 emitDecoratorMetadata
以下是使用 typegoose 的示例(下面的代码使用 ~7.4 版本的选项扩展):
export class SystemInformationContent {
  @Prop({ required: true })
  createdAt: number;

  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: () => User })
  createdBy: Ref<User>;

  @Prop({ default: 0 })
  updatedAt?: number;

  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: () => User }) // default is "undefined"
  updatedBy?: Ref<User>;
}

export class SystemInformation {
  @Prop() // thanks to "emitDecoratorMetadata" no explicit types are needed 
  system: SystemInformationContent;

  // but if wanting to do explicit types
  @Prop({ type: () => SystemInformationContent })
  system: SystemInformationContent;
}

附注:我不知道你的raw函数来自哪里,但这不是一个typegoose函数。


嗨,我正在使用NestJS,它使用了自己的typegoose实现(https://github.com/kpfromer/nestjs-typegoose)。 非常感谢您的回答,我会研究一下! - Falcort
1
我尝试了你的解决方案,但它没有起作用,emitDecoratorMetadata 已启用,但我认为 NestJS Typegoose 不是这样工作的... - Falcort

0
如果我理解正确,这就是你想要的东西。你只是错过了对于SystemInformationContent@Schema() 注释,并且需要在任何需要的地方继承该模式。我曾经遇到过类似的问题。所以,如果这不是你要求的,请告诉我。
@Schema()
export class SystemInformationContent {
  // put your @Prop() attributes here, that need to be available in every other schema
}

@Schema()
export class SystemInformation extends SystemInformationContent {
  // no need to do anything else here
  // the attributes are inherited from SystemInformationContent 
}

嘿,伙计,这不是我要找的解决方案,但出于某种原因,你的答案在我的脑海中打开了一些东西,让我找到了解决方案,非常感谢! - Falcort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接