wujekkiryl
wujekkiryl

Reputation: 91

NestJS with mongoose schema, interface and dto approach question

I am new into nestJS and mongoDB and its not clear for me why do we need to declare DTO, schema and interface for each collection we want to save in our mongoDB. IE. I have a collection (unfortunately I've named it collection but it does not matter) and this is my DTO:

export class CollectionDto {
  readonly description: string;
  readonly name: string;
  readonly expiration: Date;
}

interface:

import { Document } from 'mongoose';

export interface Collection extends Document {
  readonly description: string;
  readonly name: string;
  readonly expiration: Date;
}

and schema:

import * as mongoose from 'mongoose';

export const CollectionSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  description: {
    type: String,
    required: false,
  },
  expiration: {
    type: String,
    required: true,
  }
});

My doubt is that do we really need as many as three objects with almost the same contents? It looks strange at first sight.

Upvotes: 5

Views: 12512

Answers (1)

Arturo Castro
Arturo Castro

Reputation: 311

I was working with mongoose a lot in plain nodejs basis and as well I'm starting to work with NestJS. Mongoose defines two things so that you can use mongodb to create, query, update and delete documents: Schema and Model. You already have your schema, and for model in plain mongoose should be as:

import * as mongoose from 'mongoose';

export const CollectionSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  description: {
    type: String,
    required: false,
  },
  expiration: {
    type: String,
    required: true,
  }
});
const Collection = mongoose.model('collections', CollectionSchema);

Collection here will be mongoose model. So far so good.

In NestJs, and if you are going to follow API best practices, you will use a DTO (Data Transfer Object). NestJs in doc mention that is preferable to use classes than interfaces, so you don't need interfaces here. When you define Mongoose schema, you can also define Model/Schema:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type CollectionDocument = Collection & Document;

@Schema()
export class Collection {
  @Prop()
  name: string;

  @Prop()
  description: number;

  @Prop()
  expiration: string;
}

export const CollectionSchema = SchemaFactory.createForClass(Collection);

And for your services and controllers you use both (model and DTO):

import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Collection, CollectionDocument } from './schemas/collection.schema';
import { CollectionDto } from './dto/collection.dto';

@Injectable()
export class CollectionService {
  constructor(@InjectModel(Collection.name) private collectionModel: Model<CollectionDocument>) {}

  async create(createColDto: CollectionDto): Promise<Collection> {
    const createdCollection = new this.collectionModel(createColDto);
    return createdCollection.save();
  }

  async findAll(): Promise<Collection[]> {
    return this.collectionModel.find().exec();
  }
}

After this, you can user Swagger to automatic doc of your APIs. NestJS Mongo Techniques

Upvotes: 9

Related Questions