《Nest系列 - 4. 听说人人都会CRUD,可是我还不会怎么办???-《4.3结合前端使用实现多表联合查询》

🍑 联合查询

在我们前端来说,会抽离一些公用组件。不会把重复的组件或者所有代码都放在一个文件夹下。对于后端来说,也是一样的, 我们不会把所有数据都放在一张表里,我们回进行分表,根据一些关联关系,进行联合查询
这样可以消除冗余,并且可以提高查询的效率

🥑 效果展示

在这里插入图片描述

tags 表中也多了对应的数据

image.png

🧐 分析

  • 用户对于标签的关系 一个用户可以拥有多个标签(一对多)
  • 多个标签对应一个用户 (多对一)

image.png

🤔 用户表和标签表怎么做关联

操作数据库,使用typeorm,里面有两个装饰器OneToManyManyToOne 这两个装饰器就是做数据库关联关系

  • tags.entity.ts

import { Column, Entity, PrimaryGeneratedColumn, BeforeInsert, CreateDateColumn, Generated, OneToOne, JoinColumn, ManyToOne } from 'typeorm'
import { User } from './user.entity'
@Entity()
export class Tags {
    // 递增主键
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    tags:string
    
 // 多对一,回调函数,帮助Tags 表 和 User 表建立关联。第一个参数是User实体类, 第二个参数(回调函数)是关联的字段
    @ManyToOne(()=>User,(user)=>user.tags)
    @JoinColumn()
    user:User
} 
  • user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, OneToMany } from 'typeorm';
import { Tags } from './tags.entity';

// 表名
@Entity({ name: 'users' })
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 30, nullable: true, comment: 'user name' })
  name: string;

  @Column({ nullable: true, comment: 'user age' })
  age: number;

  @CreateDateColumn({ name: 'created_at', type: 'datetime', comment: 'created time' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at', type: 'datetime', comment: 'updated time' })
  updatedAt: Date;
  // 用户对标签事一对多关系,帮助User 表和 Tag 表建立关联。第一个参数事Tags 实体类,第二个参数(回调函数) 是关联的字段
  @OneToMany(() => Tags, (tags) => tags.user)
  tags:Tags[]
  
}

👱 前端部分逻辑

其实前端并不关心你是怎么关联的,我只调用相应的接口,传递相应的字段,后端做处理就行

//添加tag 接口
export const addTags = (data) => axios.post(`/user/add/tags`, data).then((res) => res.data)
// 模版显示
<el-dialog v-model="isShowTag" title="添加tag">
		<el-select style="width: 100%" v-model="tags" multiple>
			<el-option value="tag1">tag1</el-option>
			<el-option value="tag2">tag2</el-option>
			<el-option value="tag3">tag3</el-option>
		</el-select>
		<template #footer>
			<el-button @click="addTa" type="primary">确定</el-button>
		</template>
	</el-dialog>
// js 接口调用
 const addTa = async () => {
    await addTags({
        tags: tags.value,
        userId: row.value.id
    })
	isShowTag.value = false
	tags.value = []
	init()
}

🧓 后端部分逻辑

💻 controller

  • 前端是通过user/add/tags 路由传递来的,那后端路由要做相应的匹配
  • 前端会传来tags 和 userId ,那controller 这一层要通过对应的装饰器来对参数进行解析
  • 最后调用serveice 里的方法,并且传递解析完的参数,进行对数据的操作
@Post('/add/tags')
  addTags(@Body() params:{tags: string[], userId:number}) {
    return this.userService.addTags(params);
  }

💻 service

添加标签主要有这么几步

  • 在service 定义 addTags方法
  • 根据用户id找到当前用户的信息(因为要往指定用户下添加信息)
  • 将传递来的tag 数据添加到Tag 表中
  • 更新当前用户的数据到User表中
async addTags(params:{tags: string[], userId: number}){
    // 根据id 找到当前用户信息
    const userInfo = await this.usersRepository.findOne({where:{ id: params.userId}})
    
    const tagList:Tags[] = []
    // 通过循环,将tags 存入数据库
    for (let i = 0; i < params.tags.length; i++) {
      const T = new Tags()
      T.tags = params.tags[i]
      await this.tagsRepository.save(T)
      tagList.push(T)
    }
    // 更新当前用户的tags
    userInfo.tags = tagList
    // 将当前用户更新的值,存入到数据库
    return await this.usersRepository.save(userInfo) 
  }  

关联查询,使用 relations 关键字,传入关联的表即可

async findAll(query:{keyWord: string, page: number, pageSize: number }) {
    const data =  await this.usersRepository.find({
      //查询的时候如果需要联合查询需要增加 relations
      relations:['tags'],

      where: {
        name: Like(`%${query.keyWord}%`)
      },
      order: {
        id: "DESC"
      },
      skip: (query.page - 1)* query.pageSize,
      take: query.pageSize,
    })
    const total = await this.usersRepository.count({
      where: {
        name: Like(`%${query.keyWord}%`)
      },
    })

    return {
      data,
      total
    }
  }

🎊 总结

  • 对于联合查询,前端还是普通的传递参数,调用接口。这是后端做一个一个拆分。相当于前端拆组件,再拼接起来。
  • 联合查询有很多关系,一对多,多对一,多对多,等等。主要实现是通过typeorm,里面的装饰器OneToManyManyToOne, ManyToMany 具体可参考TypeORM 关系这一章 https://typeorm.bootcss.com/relations
  • 表关联完毕,就是数据怎么做关联
  • 根据id,找到对应的用户。
  • 根据传递来的tag,依次添加到tag 表中
  • 更新当前用户的值
  • 查询时 如果需要 联合查询需要增加 relations:['tags'] 即可,代表关联查询那张表

🏠 项目地址

  • Vue 前端地址:
    https://gitee.com/Big_Cat-AK-47/vue-project

  • nest 后端地址:https://gitee.com/Big_Cat-AK-47/nest

🎉 Nest 系列 往期文章

1. 《Nest系列 - 1. 🔥运行一个Nest项目以及整体目录学习》

2. 《Nest系列 - 2. 🔥Nest 代码生成器,让你告别base代码书写!!!》

3. 《 Nest系列 - 3. 🔥掌握常见Nest 装饰器,奠定坚实基础!!!!!!》

4. 《Nest系列 - 4. 🔥听说人人都会CRUD,可是我还不会怎么办???-《 4.1-数据库连接和实体》》

5. # 《Nest系列 - 4. 🔥听说人人都会CRUD,可是我还不会怎么办???-《4.2结合前端使用实现CRUD》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值