포시코딩

[TypeORM] FK 설정 후 join해서 데이터 가져오기 본문

Node.js

[TypeORM] FK 설정 후 join해서 데이터 가져오기

포시 2023. 2. 17. 07:39
728x90

개요

어떤 게시글(Boards)에 대해 '참여하기' 기능이 있어 

해당 게시글에서 '참여하기' 버튼을 누르면 제한된(joinLimit) 숫자 내에서 

유저가 참여하게끔 기능을 구현하고자 한다.

 

그럼 먼저 테이블이 두 개가 필요하다. 

  • 게시글 테이블: Boards
  • 해당 게시글에 대해 참여한 유저를 담는 테이블: Join 

유저 테이블도 필요한데 이번 과정에선 생략

 

FK 설정

entity를 통해서 설정이 가능하다.

게시글과 join은 1:N 관계이므로 OneToMany가 되어야 한다.

 

board.entity.ts

import {
  // ...생략
} from 'typeorm';
import { Join } from './join.entity';

@Entity({ schema: 'nestjs_sample', name: 'boards' })
export class Board {
  @PrimaryGeneratedColumn({ type: 'int', name: 'id' })
  id: number;

  @Column('varchar', { length: 50 })
  title: string;

  @Column('varchar', { length: 1000 })
  content: string;

  @Column('int')
  writerId: number;

  @Column('int')
  joinLimit: number;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date | null;

  @OneToMany((type) => Join, (join) => join.board)
  joins: Join[];
}

 

join.entity.ts

import { Entity, ManyToOne, PrimaryColumn } from 'typeorm';
import { Board } from './board.entity';

@Entity({ schema: 'nestjs_sample', name: 'join' })
export class Join {
  @PrimaryColumn()
  boardId: number;

  @PrimaryColumn()
  userId: number;

  @ManyToOne((type) => Board, (board) => board.joins)
  board: Board;
}

 

서버 실행 시 Join 테이블쪽에서 종속관계가 형성된 것을 확인할 수 있다.

 

Join

async getBoards(): Promise<Board[]> {
  return await this.boardRepository.find({
    where: { deletedAt: null },
    select: ['id', 'title', 'writerId', 'joinLimit', 'createdAt'],
  });
}

기존에 Join 테이블과 join 하지 않은 상태일 때 불러오던 데이터들. 

(어쩌다보니 테이블 명을 Join으로 지어서 테이블 합치는 join 명령어와 헷갈릴 수 있는데 주의해주시길..!)

 

위에서 종속 관계를 만들어놨기 때문에 Repository에 대해 join 관련 함수를 사용할 수 있다.

또한 몰랐는데 

where: { deletedAt: null },

softDelete 된 데이터에 대해서는 굳이 deletedAt: null 값으로 찾지 않아도 

알아서 TypeORM이 걸러 찾아준다.

 

  async getBoards(): Promise<Board[]> {
    return await this.boardRepository
      .createQueryBuilder('boards')
      .leftJoinAndSelect('boards.joins', 'join')
      .getMany();
  }

join할 데이터가 없는건 [] 빈 array로 반환된다.

이렇게 join을 한 상태로 데이터를 잘 가져오는 것을 확인했다.

 

근데 leftJoinAndSelect()만 써서 가져와서 그런지 원치 않는 데이터까지 다 가져오고 있어서

정리가 좀 필요해보인다. 

위에서 select를 통해 특정 컬럼 값들만 가져왔듯, 구현해보자

 

  async getBoards(): Promise<Board[]> {
    return await this.boardRepository
      .createQueryBuilder('boards')
      // .leftJoinAndSelect('boards.joins', 'join')
      .leftJoin('boards.joins', 'join')
      .select([
        'boards.id',
        'boards.title',
        'boards.writerId',
        'boards.joinLimit',
        'boards.createdAt',
        'join.userId',
      ])
      .getMany();
  }

직접 select() 함수를 사용하고 있기 때문에 leftJoinandSelect() 대신 leftJoin()를 썼으며

컬럼은 기존 값들에 join.userId만 추가했다. 

 

결과는 다음과 같다.

추후에 해당 userId에 대해 유저 데이터를 연결해서 사용하면 될 것 같다.

오늘은 요기까지

 

 

 

참고한 곳

https://overcome-the-limits.tistory.com/600

 

[TypeORM] TypeORM 관계 설정하기

들어가며 TypeORM에 대해 아무런 지식이 없습니다. 하지만 NestJS로 개발을 하려면, TypeORM에 대한 깊은 이해가 필요하겠다고 생각했습니다. 잘 모르지만, 삽질해가면서 TypeORM에 대해 공부해보고자

overcome-the-limits.tistory.com

https://velog.io/@josworks27/TypeORM-Join

 

TypeORM으로 Join 하기

이번 로그에서는 TypeORM을 이용하여 Join하는 방법에 대해 기록하고자 한다. TypeORM에서는 Query Builer라고 하는 쿼리 검색을 도와주는 강력한 헬퍼기능이 있다. 이 Query Builder를 이용하여 Left, Inner 조

velog.io

 

728x90