Boilerplate supports two types of databases: PostgreSQL with TypeORM and MongoDB with Mongoose. You can choose one of them or use both in your project. The choice of database depends on the requirements of your project.
For support of both databases used Hexagonal Architecture.
Create entity file with extension .entity.ts
. For example post.entity.ts
:
// /src/posts/infrastructure/persistence/relational/entities/post.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import { EntityRelationalHelper } from '../../../../../utils/relational-entity-helper';
@Entity()
export class Post extends EntityRelationalHelper {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
body: string;
// Here any fields that you need
}
Next, generate migration file:
npm run migration:generate -- src/database/migrations/CreatePostTable
Apply this migration to database via npm run migration:run.
npm run migration:run
npm run migration:revert
npm run schema:drop
Create entity file with extension .schema.ts
. For example post.schema.ts
:
// /src/posts/infrastructure/persistence/document/entities/post.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
export type PostSchemaDocument = HydratedDocument<PostSchemaClass>;
@Schema({
timestamps: true,
toJSON: {
virtuals: true,
getters: true,
},
})
export class PostSchemaClass extends EntityDocumentHelper {
@Prop()
title: string;
@Prop()
body: string;
// Here any fields that you need
}
export const PostSchema = SchemaFactory.createForClass(PostSchemaClass);
npm run seed:create:relational -- --name=Post
. Where Post
is name of entity.src/database/seeds/relational/post/post-seed.service.ts
.run
method extend your logic.npm run seed:run:relational
Install faker:
npm i --save-dev @faker-js/faker
Create src/database/seeds/relational/user/user.factory.ts
:
import { faker } from '@faker-js/faker';
import { RoleEnum } from '../../../../roles/roles.enum';
import { StatusEnum } from '../../../../statuses/statuses.enum';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RoleEntity } from '../../../../roles/infrastructure/persistence/relational/entities/role.entity';
import { UserEntity } from '../../../../users/infrastructure/persistence/relational/entities/user.entity';
import { StatusEntity } from '../../../../statuses/infrastructure/persistence/relational/entities/status.entity';
@Injectable()
export class UserFactory {
constructor(
@InjectRepository(UserEntity)
private repositoryUser: Repository<UserEntity>,
@InjectRepository(RoleEntity)
private repositoryRole: Repository<RoleEntity>,
@InjectRepository(StatusEntity)
private repositoryStatus: Repository<StatusEntity>,
) {}
createRandomUser() {
// Need for saving "this" context
return () => {
return this.repositoryUser.create({
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
email: faker.internet.email(),
password: faker.internet.password(),
role: this.repositoryRole.create({
id: RoleEnum.user,
name: 'User',
}),
status: this.repositoryStatus.create({
id: StatusEnum.active,
name: 'Active',
}),
});
};
}
}
Make changes in src/database/seeds/relational/user/user-seed.service.ts
:
// Some code here...
import { UserFactory } from './user.factory';
import { faker } from '@faker-js/faker';
@Injectable()
export class UserSeedService {
constructor(
// Some code here...
private userFactory: UserFactory,
) {}
async run() {
// Some code here...
await this.repository.save(
faker.helpers.multiple(this.userFactory.createRandomUser(), {
count: 5,
}),
);
}
}
Make changes in src/database/seeds/relational/user/user-seed.module.ts
:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserSeedService } from './user-seed.service';
import { UserFactory } from './user.factory';
import { UserEntity } from '../../../../users/infrastructure/persistence/relational/entities/user.entity';
import { RoleEntity } from '../../../../roles/infrastructure/persistence/relational/entities/role.entity';
import { StatusEntity } from '../../../../statuses/infrastructure/persistence/relational/entities/status.entity';
@Module({
imports: [TypeOrmModule.forFeature([UserEntity, Role, Status])],
providers: [UserSeedService, UserFactory],
exports: [UserSeedService, UserFactory],
})
export class UserSeedModule {}
Run seed:
npm run seed:run
npm run seed:create:document -- --name=Post
. Where Post
is name of entity.src/database/seeds/document/post/post-seed.service.ts
.run
method extend your logic.npm run seed:run:document
Don’t forget to create indexes
on the Foreign Keys (FK) columns (if needed), because by default PostgreSQL does not automatically add indexes to FK.
Set the optimal number of max connections to database for your application in /.env
:
DATABASE_MAX_CONNECTIONS=100
You can think of this parameter as how many concurrent database connections your application can handle.
Designing schema for MongoDB is completely different from designing schema for relational databases. For best performance, you should design your schema according to:
Previous: Command Line Interface
Next: Auth