Search code examples
mongooseswaggernestjs

Swagger doesn't show _id from mongoose schema


I trying to use swagger to get better helps with api request in my project. Everything is great but i have problem with displaying _id property from mongo document.

I don't know exactly how i can attach _id in my document model let swagger see it.

For example i have user document which looks like this

export class User extends Document {
  @ApiProperty({ description: 'The username of the user' })
  @Prop({ type: String, required: true })
  username: string;

  @ApiProperty({ description: 'The email of the user' })
  @Prop({ required: true })
  email: string;

  @ApiProperty({ description: 'The hashed password of the user' })
  @Prop({ required: true, min: 6 })
  password: string;

  @ApiProperty({ description: 'User roles' })
  @Prop({
    type: [{ type: String, enum: UserRole }],
    default: [UserRole.Customer],
  })
  role: string[];

  @ApiProperty({ description: 'User billing details' })
  @Prop({ type: BillingSchema, default: new Billing() })
  billing: Billing;

  @ApiProperty({ description: 'Information about user account status' })
  @Prop({ type: Boolean, default: false })
  isActive: boolean;

  @ApiProperty({ description: 'User activation token used to account activation' })
  @Prop({ type: String || null, default: null })
  activationToken: string | null;

  @ApiProperty({ description: 'User reset password token used to reset password' })
  @Prop({ type: String || null, default: null })
  resetPasswordToken: string | null;

  @ApiProperty({ description: 'List of user bought products', type: Product, isArray: true })
  @Prop([{ type: mongoose.Schema.Types.ObjectId, ref: 'Product' }])
  products: Product[];

  @ApiProperty({ description: 'Date of register' })
  @Prop({ type: Date })
  createdAt: Date;

  @ApiProperty({ description: 'Date of account last update' })
  @Prop({ type: Date })
  updatedAt: Date;
}

any my User schema in swagger looks like this:

User{
username*   [...]
email*  [...]
password*   [...]
role*   [...]
billing*    {...}
isActive*   [...]
activationToken*    [...]
resetPasswordToken* [...]
products*   [...]
createdAt*  [...]
updatedAt*  [...]
}

I'll be grateful for any tips or help with solving that issue.


Solution

    1. If you using nestjs plugin with swagger cli
    {
      "$schema": "https://json.schemastore.org/nest-cli",
      "collection": "@nestjs/schematics",
      "sourceRoot": "src",
      "compilerOptions": {
        "deleteOutDir": true,
        "plugins": [
          {
            "name": "@nestjs/swagger",
            "options": {
              "introspectComments": true,
              "dtoFileNameSuffix": [
                ".dto.ts",
                ".schema.ts"
              ]
            }
          }
        ]
      }
    }
    
    1. You can define a virtual prop "id" as string.
    import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
    import { HydratedDocument } from 'mongoose';
    
    export type AuthorDocument = HydratedDocument<Author>;
    
    @Schema({
      toJSON: {
        versionKey: false,
        // this option will show id prop in your schema.
        virtuals: true,
      },
    })
    export class Author {
      id: string;
      /**
       * the author's fisrt name
       * @example Jone
       */
      @Prop({
        type: String,
        required: true,
      })
      first_name: string;
    
      /**
       * the author's birthday
       */
      @Prop({
        type: Date,
      })
      date_of_birth?: Date;
    }
    
    1. Exclude the id prop in your create dtos,you can use OmitType.
    import { OmitType } from '@nestjs/swagger';
    import { Author } from '../schemas/author.schema';
    
    export class CreateAuthorDto extends OmitType(Author, ['id']) {
        
      /**
       * @example 2023-07-18
       */
      date_of_birth?: Date;
    }
    
    1. Use the schema type in your service.
    import { Injectable } from '@nestjs/common';
    import { CreateAuthorDto } from './dto/create-author.dto';
    import { UpdateAuthorDto } from './dto/update-author.dto';
    import { InjectModel } from '@nestjs/mongoose';
    import { Author } from './schemas/author.schema';
    import { Model } from 'mongoose';
    
    @Injectable()
    export class AuthorsService {
      constructor(
        @InjectModel(Author.name) private readonly authorModel: Model<Author>,
      ) {}
    
      async create(createAuthorDto: CreateAuthorDto): Promise<Author> {
        const author = new this.authorModel(createAuthorDto);
        return await author.save();
      }
    
      async findAll(): Promise<Author[]> {
        return await this.authorModel.find().exec();
      }
    
    }
    
    1. Result.

    swagger result