관련글 1 : https://s0n9h2.tistory.com/109
[01 들어가기에 앞서 ]
- 저번 포스팅에서 1:1, 1:N, 1:M 관계 설정에 대해 다뤘는데, 이렇게 설정해 둔 외래키로 어떻게 참조 테이블을 검색할 수 있을지 작성해보겠다.
- 처음 나와 팀원은 당연히(?) 그냥 findAll 혹은 findOne의 where문에 외래키를 넣어주면 된다고 생각했는데, 모델을 생성할 때 Attributes에 외래키가 들어가지 않고 관계 설정시에 컬럼이 추가되기 때문에 외래키를 바로 참조할 수 없었다.
- 따라서 검색을 해보니 핵심은 외래키가 있는 참조 테이블을 include 하는 것이었는데, 아래에서 자세하게 설명해보겠다.
[02 모델 구조 ]
- 먼저 이해를 돕기 위해 Checklists 의 ERD 설계와 모델의 Attributes는 다음과 같다.
- 위와 같이 외래키 fk_user_id 는 모델 생성시에 Attributes에 있는 것이 아니라 관계 설정시에 외래키 컬럼으로 추가된다.
[03 옵션 설정 ]
- sequelize 쿼리 함수를 사용하는 DB 계층 파일 Checklist.ts 에 작성했다.
(1) where, include
- 먼저 findByDate 메소드는 사용자가 오늘 체크리스트를 작성했는지 확인하기 위한 기능이다. 따라서 fk_user_id와 date를 기준으로 데이터가 존재하는지 검색해야 한다.
- 이 때 fk_user_id 는 외래키이므로 include 옵션을 사용해 model 은 Users (fk_user_id가 참조하는 테이블), where 에 { Users 테이블에서의 fk_user_id 컬럼명: fk_user_id } 를 설정해주면 된다.
- include는 말 그대로 다른 모델을 "포함"해서 검색하고 응답한다고 이해했다. 따라서 그 모델에서 필터링할 것(where)과 보여줄 속성(attributes)을 include 옵션 안에서 지정해줄 수 있다.
- 그리고 date 는 Checklists 모델의 컬럼이기 때문에 include 와 함께 바깥 where 문에 설정해줘야 한다.
findByDate: async (fk_user_id: string, date: Date) => {
const checklist = await Checklists.findOne({
where: { date },
include: { model: Users, where: { pk_user_id: fk_user_id } },
});
return checklist;
}
(2) attributes, order
- 여기서 추가로 Op(연산자)와 더 많은 옵션을 사용해서 구체적인 필터링이 가능하다.
- findByWeek 메소드는 사용자가 일주일동안 체크한 체크리스트의 level을 보여주는 기능이다. 따라서 fk_user_id와 일주일의 시작 날짜(start), 끝나는 날짜(finish)를 기준으로 검색해야 한다.
- 외래키 검색은 위의 예시와 비슷하게 하되, Users 모델의 정보는 필요 없기에 attributes 옵션을 [ ] (빈 값)으로 설정했다.
- attributes도 말 그대로 보여줄 속성을 정해주는 옵션이다. include로 참조 모델을 포함하면 findAll 함수의 경우 응답의 데이터 양이 엄청 많아지기 때문에 모든 컬럼이 필요하지 않다면 attributes로 필요한 컬럼만 지정해주는 것이 좋다.
- 또 Checklists 모델에서도 1~6번의 항목값은 필요 없기 때문에 attributes 옵션을 이용해 date와 level만 보여주도록 설정했다.
- 마지막으로 시간순으로 정렬하기 위해 order 옵션을 이용해서 date 컬럼을 ASC (오름차순)으로 설정했다.
- 이러한 정렬은 date 컬럼이 dateonly 혹은 datetime 타입일 때 가능하다. 이외에 시간순으로 정렬이 필요하다면 created_at이나 updated_at 컬럼을 사용해야 할 것이다.
- 내림차순은 DESC 이다.
- 여러 컬럼을 기준으로 정렬하고 싶다면 [ ] 안에 정렬할 순서대로 ["컬럼명", "정렬기준"]을 추가한다.
findByWeek: async (fk_user_id: string, { start, finish }: IChecklistWeeklyInput) => {
const checklists = await Checklists.findAll({
attributes: ["date", "level"],
where: { date: { [Op.between]: [start, finish] } },
include: { model: Users, attributes: [], where: { pk_user_id: fk_user_id } },
order: [["date", "ASC"]],
});
return checklists;
}
- Op 연산자 종류와 사용하는 방법은 다음 포스팅으로 다뤄보겠다.
'엘리스 AI트랙 4기 > 프로젝트' 카테고리의 다른 글
[TypeScript Express] Sequelize의 Getters와 Setters (0) | 2022.06.18 |
---|---|
Sequelize에서 where문에 연산자(Operator) 사용하기 (0) | 2022.06.17 |
[TypeScript Express] Sequelize로 MySQL 모델 Association 관계 설정하기 (0) | 2022.06.15 |
[TypeScript Express] Sequelize로 MySQL 기본 모델 생성하기 (0) | 2022.06.14 |
[TypeScript Express] 라우터, 컨트롤러, 미들웨어 분리 (0) | 2022.06.10 |