Web Backend App: Adding a formatted Id to a document using Mongoose virtuals with MongoDB,Nest.js
Tags: mongodb, node, typescript, nestjs
Published: 2020-06-10 08:06:52

Project ID format – PR0001

The reader is a class which returns the json response object.
The field "_formattedId" is a virtual field which does not exist in Database.
Instead, a number field "formattedId" stores the index of the Project.
So,if the "formattedId" value is 1,10,100, the value of the "_formattedId" will be "PR0001","PR0010","PR0100".
These values are created by passing the "formattedId" values to pad function with width and z as additional arguments.
[link]
Link: https://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript
**Code:**
*src\sme-project\objects\sme-project.dto.ts*
import { Expose, Type } from "class-transformer";
import {
  IsNotEmpty,
  IsDefined,
  MaxLength,
  IsOptional,
  ValidateNested,
  IsString,
  IsIn,
  IsInt,
} from "class-validator";
import { Reader, Creator, Updater } from "../../common/base/base.dto";

export class SmeProjectDto extends Reader {
  
  @Expose()
  readonly **_formattedId: string = "";**

}

export class CreateSmeProjectDto extends Creator {
  constructor() {
    super(true);
  }
  @IsDefined()
  @IsNotEmpty()
  @IsString()
  @MaxLength(20, { message: "FundsRequired is too long" })
  @ApiModelProperty()
  readonly **fundsRequired: string;**
}

*src\sme-project\objects\sme-project.schema.ts*
export class SmeProject extends Entity {
    **formattedId: number;**
}

export interface ISmeProject extends SmeProject, IEntity {
  id: string;
}

Only the fields in the Schema are stored in the database.Here "formattedId" field is stored in the database.

**Code:**
*src\sme-project\objects\sme-project.schema.ts*
import { Entity, IEntity, createModel } from "../../common/base/base.model";
import { Schema } from "mongoose";
import { pad } from "../sme-project.service";

export const **SmeProjectSchema**: Schema = createModel("SmeProjects", {
     **formattedId: { type: Number, required: true}**
});

SmeProjectSchema.virtual("_formattedId").get(function() {
  return **this._formattedId** = "PR" + **pad(this.formattedId, 4, 0)**;
  }
);

In the service class,we create another field "formattedId" which is equal to "total number of records + 1",since a new record is being created.
*src/sme-project/sme-project.service.ts*
**Code:**
import { Injectable } from "@nestjs/common";
import { Model } from "mongoose";
import { BaseService } from "../common/base/base.service";
import { ISmeProject } from "./objects/sme-project.schema";
import { InjectModel } from "@nestjs/mongoose";
import { CanLoadVirtual } from "../common/interfaces/can.load.virtual";

import { Paginate } from "src/common/interfaces/pagination";

export function **pad(n, width, z)** {
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

@Injectable()
export class SmeProjectService extends BaseService<ISmeProject>
  implements CanLoadVirtual {
  constructor(
    @InjectModel("SmeProject")
    private readonly smeProjectModel: Model<ISmeProject>
  ) {
    super(smeProjectModel);
  }
  async doPreCreate(createDto: Partial<ISmeProject>): Promise<void> {
    let options: Paginate = {limit: 30, page: 1, sort: "_id"};
    let query = null;
    let _projects = await this.findAll(query,options);
    **createDto["formattedId"] = _projects.total + 1;**
  }

  }
}
My Github Profile for code:
Please see the develop branch in my repo.
[Link]https://github.com/krishnakurtakoti/nestTwo