200. Database
Intro
- Database | NestJS - A progressive Node.js framework
- Nest is database agnostic, allowing you to easily integrate with any SQL or NoSQL database.
- For convenience, Nest provides tight integration with
- TypeOrm
@nestjs/typeorm
- Sequelize
@nestjs/sequelize
- Mongoose
@nestjs/mongoose
- but still you have the options to use any orm of your choice
- TypeOrm
Using TypeOrm
- To begin using typeorm, we first install the required dependencies.
npm i @nestjs/typeorm typeorm pg
#pg = because we're using postgres, but can be mysql or sth-else
- Once the installation process is complete, we can import the
TypeOrmModule
into the rootAppModule
.- To learn more about the options we can pass to TypeOrm check (Site Unreachable)>
//...imports
@Module({
imports: [
CoffesModule,
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'pass123',
database: 'postgres',
autoLoadEntities: true,
synchronize: true, //sync local entity to db entities, warnning must be diabled in production
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
TypeOrmModule.forRoot, should only be called once at the root module, for child modules, you need to use .forFeature() method
Is Typeorm Running
- to check if application, typeorm and db, all are connected and working
- just run the application with
npm run start:dev
- and you should see no error, but a log specifying
typeorm has been initialized
- ex:
TypeOrmModule dependencies initialized
- ex:
- just run the application with
Creating Typeorm Entity
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column({ default: true })
isActive: boolean;
}
- To begin using the
User
entity, we need to let TypeORM know about it by inserting it into theentities
array in the moduleforRoot()
method andforFeature()
method of the domain module
@Module({
imports: [
TypeOrmModule.forRoot({
//...
entities: [User],
synchronize: true,
}),
],
})
export class AppModule {}
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}
if you are using autoloadentities:true in .forRoot configurations, you only have to add your entities inside for .forFeature, then nest will take care of the registration. Database | NestJS - A progressive Node.js framework
- using typorm users repository inside services
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
findAll(): Promise<User[]> {
return this.usersRepository.find();
}
findOne(id: number): Promise<User | null> {
return this.usersRepository.findOneBy({ id });
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}
you can export TypeOrm repositories so they can be used in another module/service. Database | NestJS - A progressive Node.js framework
Creating DB Relations
- What are Relations? | TypeORM
- creating relations
- we can create 1-1, 1-m(m-1), and m-m
- how to save and get a relation while performing CRUD
//creating 1-m relationship
@Entity()
export class User{
@OneToMany(type => Photo, photo => photo.user)
photos: Photo[];
}
//saving relations
const photo1 = new Photo()
photo1.url = "me.jpg"
await photoRepo.save(photo1)
const photo2 = new Photo()
photo2.url = "me-and-bears.jpg"
await photoRepo.save(photo2)
const user = new User()
user.name = "John"
user.photos = [photo1, photo2]
await userRepo.save(user)
//reading relations
const users = await userRepo.find({
relations: {
photos: true,
},
})
Typeorm Transaction
- Transactions | TypeORM
- Database | NestJS - A progressive Node.js framework
- First, we need to inject the
DataSource
object into a class in the normal way:
@Injectable()
export class UsersService {
constructor(private dataSource: DataSource) {}
}
- run your transaction
async createMany(users: User[]) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await queryRunner.manager.save(users[0]);
await queryRunner.manager.save(users[1]);
await queryRunner.commitTransaction();
} catch (err) {
// since we have errors lets rollback the changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release a queryRunner which was manually instantiated
await queryRunner.release();
}
}
More on Typeorm
- typeorm indexes
- single index
- composite index
- typeorm migration
- Database | NestJS - A progressive Node.js framework
- Migration is handled separetly by typeorm cli