Search code examples
mongoosenestjstypegoose

NestJS MongoDB nested object schema


I am currently running the code :

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;
}

I did not found any way of "extending" the schema of SystemInformationContent and so used the raw() function in the @Prop() decorator, but I am wondering if there is a way to do something like this:

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;
}

I did not found anything working to put into the SystemInformation.system @Prop() that take in account the schema of SystemInformationContent.

Do you guys know if there is an other way than the raw or if I am missing something ?

Edit: All classes of my NestJS application are extending SystemInformation so they all look like :

{
  ...,
  system: {
    createdAt: 1616778310610,
    createdBy: "605e14469d860eb1f0641cad",
    editedAt: 0,
    createdBy: null,
  },
}

Solution

  • Found a solution !

    I edited SystemInformationContent to :

    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,
    );
    

    Then in SystemInformation I edited to :

    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;
    }
    

    Now everything is working, I used the @Schema({ _id: false }) to remove the ID generated by the SchemaFactory so I end up with that in the DB :

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