nest学习笔记(6) :联通数据库的CRUD操作以及高级查询
重新回忆依赖注入
- 我们都知道
nestjs
最核心的概念就是依赖注入,所有的开发思想都是基于这个概念来实现出来的,因此nestjs
官方将所有数据库的常见操作都高度封装在TypeORM
这个核心包里面,这就意味着在项目中做CRUD
操作时,我们无需再写SQL
语句
通过上图我们可以看出,Nestjs
中的DI容器会自动的将项目中携带@Injectable
装饰符的类进行注册,最后会进一步看该类中的构造函数(Constructor
),了解对应的类与类之间的依赖关系之后进行对应类实例的创建,在项目中用的时候引入即可!
CRUD
操作
关联查询: 一对一,一对多
一对一
- 所谓一对一关联查询,就是在数据库中,某一张表与另一张表建立外键约束,我们在查询其中一张表数据的时候,同时返回外键约束的那张表的对应数据,这里我们展示
User
表以及Profile
表建立的外键约束关系(UserId
)
1. 首先确定两张表的实体中都设置了一对一关系(OneToOne
)
import {
OneToOne, } from 'typeorm'; import { Profile } from './profile.entities';
@Entity() export class User {
@OneToOne(() => Profile, (profile) => profile.user)
profile: Profile; }
import {
OneToOne, } from 'typeorm'; import { User } from './user.entities';
@Entity() export class Profile {
@OneToOne(() => User) @JoinColumn({ name: 'user_id' }) user: User;
}
|
2. 编写查询的业务逻辑(开启relations
属性)
import { Injectable } from '@nestjs/common';
import { Like, Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from './entities/user.entities';
@Injectable() export class BoysService { constructor( @InjectRepository(User) private readonly users: Repository<User>, ) {}
findUser_Profile(id: number) { return this.users.findOne({ where: { id, }, relations: { profile: true, }, }); } }
|
3. 编写一对一关联查询接口
import { Controller, Get,
Inject, } from '@nestjs/common'; import { BoysService } from './boys.service';
@Controller('boys') export class BoysController { constructor( @Inject('boys') private BoysService: BoysService, ) {
}
@Get('/user_profile') getUser_Profile(): any { return this.BoysService.findUser_Profile(1); } }
|
结果展示:
一对多/多对一
- 一对多以及多对一与上面的想法是基本一致,其实关键都是看通过谁去查询谁,这个是重点,是通过一个用户id去查询该用户的同时顺带查询该用户的全部logs数据还是再查询对应logs数据的同时顺带查询该条logs数据是属于哪一个用户的
1. 首先确定两张表都设置了一对多/多对一关系
import {
ManyToOne, JoinColumn, } from 'typeorm'; import { User } from '../user.entities';
@Entity() export class Logs {
@ManyToOne(() => User, (user) => user.logs) @JoinColumn({ name: 'user_id' }) user: User; }
import {
OneToMany, } from 'typeorm'; import { Logs } from './logs/logs.entities';
@Entity() export class User {
@OneToMany(() => Logs, (logs) => logs.user)
logs: Logs[]; }
|
2. 编写查询的业务逻辑(开启relations
属性)
import { Injectable } from '@nestjs/common';
import { Like, Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from './entities/user.entities'; import { Logs } from './entities/logs/logs.entities';
@Injectable() export class BoysService { constructor( @InjectRepository(Logs) private readonly logs: Repository<Logs>, ) {}
async findUser_Logs(id: number) { return this.users.find({ where: { id, }, relations: { logs: true, }, }); }
async findLogs_User(id: number) { const user = await this.findOne(id); return this.logs.find({ where: { user, }, relations: { user: true, }, }); }
findOne(id: number) { return this.users.findOne({ where: { id, }, }); } }
|
3. 编写接口
import { Controller, Get,
Inject, } from '@nestjs/common'; import { BoysService } from './boys.service';
@Controller('boys') export class BoysController { constructor( @Inject('boys') private BoysService: BoysService, ) {
} @Get('/user_logs') getUser_Logs(): any { return this.BoysService.findUser_Logs(1); }
@Get('/logs_user') getLogs_User(): any { return this.BoysService.findLogs_User(1); } }
|
4. 结果展示:
一对多查询
(查询用数据数据顺带查询该用户的logs数据)
多对一查询
(查询logs数据时顺带查询该logs数据对应的用户是谁)
QueryBuilder
的使用
官方文档
QueryBuilder
是 TypeORM
最强大的功能之一 ,它允许你使用优雅便捷的语法构建 SQL 查询,执行并获得自动转换的实体。(也就说我们可以使用QueryBuilder
实现再业务场景中多个表不同字段数据的聚合,以API
的形式去组装sql
语句,解决联合查询,分页查询,多条件查询,聚合查询等…)
网上示例:
async getUsersByPlatformName(platformName: string){ return await this.userRepo .createQueryBuilder('u') .leftJoinAndSelect('u.roles', 'r') .leftJoinAndSelect('u.plat', 'p') .where('p.isActive = :isActive', {isActive: true}) .andWhere('p.platformName like :name', { name: `%${platformName.toLowerCase()}%`}) .orderBy('age', 'DESC') .getMany(); }
|
自己的示例:
- 需求:实现查询logs表中对应的响应状态码来实现返回对应的数据条数
import { Injectable } from '@nestjs/common';
import { Like, Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { Logs } from './entities/logs/logs.entities';
@Injectable() export class BoysService { constructor( @InjectRepository(Logs) private readonly logs: Repository<Logs>, ) {}
return ( this.logs .createQueryBuilder('logs') .select('logs.result', 'result') .addSelect('COUNT("logs.result")', 'count') .leftJoinAndSelect('logs.user', 'user') .where('user.id = :id', { id }) .groupBy('logs.result') .orderBy('count', 'DESC') .addOrderBy('result', 'DESC') .limit(3) .getRawMany() ); } }
|
import { Controller, Get,
Inject, } from '@nestjs/common'; import { BoysService } from './boys.service';
@Controller('boys') export class BoysController { constructor( @Inject('boys') private BoysService: BoysService, ) {
}
@Get('/logsByGroup') async getLogsByGroup(): Promise<any> { const res = await this.BoysService.findLogsByGroup(1); return res; } }
|
结果展示: