-
TypeOrm을 사용할때 식별관계 테이블에서 find 메서드에 skip과 take 사용시 주의 해야할점Nest.js/TypeOrm 2024. 4. 10. 22:23728x90
// repository await this.repository.find({ select: { id: true, notificationTitle: true, notificationFeedId: true, createdAt: true, }, where: { recipientId, }, relations: { sender: true, }, skip, take, });
해당 쿼리가 대충 아래처럼 실행 될것이라고 예상 했지만 그렇지 않았다. FK를 가르키는 senderId를 찾을 수 없다는 에러가 나왔다.
select fn."senderId", fn."id", fn."notificationTitle", fn."createdAt", fn."senderId", fn."notificationFeedId" from fam_notification fn left join fam_member fm on fn."senderId" = fm.id where fn."senderId" ='410b7202-660a-4423-a6c3-6377857241cc' LIMIT 10 OFFSET 1
실제로 동작하는 쿼리를 살펴보니 아래와 같았다.
skip과 take를 사용한 쿼리
SELECT DISTINCT "distinctAlias"."NotificationEntity_id" AS "ids_NotificationEntity_id", "distinctAlias"."NotificationEntity_recipientId" AS "ids_NotificationEntity_recipientId", "distinctAlias"."NotificationEntity_senderId" AS "ids_NotificationEntity_senderId" FROM ( SELECT .. 조회될 필드들 FROM "fam_notification" "NotificationEntity" LEFT JOIN "fam_member" "NotificationEntity__NotificationEntity_sender" ON "NotificationEntity__NotificationEntity_sender"."id"="NotificationEntity"."senderId" WHERE ("NotificationEntity"."recipientId" = $1)) "distinctAlias" ORDER BY "NotificationEntity_id" ASC, "NotificationEntity_recipientId" ASC, "NotificationEntity_senderId" ASC LIMIT 10 OFFSET 1
흥미로웠다. ids_NotificationEntity_recipientId 와 ids_NotificationEntity_senderId 와 NotificationEntity_id 3개는
테이블의 PK이다.@PrimaryColumn('uuid') id!: string; @PrimaryColumn('uuid') public readonly recipientId!: string; @PrimaryColumn('uuid') public readonly senderId!: string;
필요에 의해서 recipientId와 senderId는 FK이지만 해당 테이블의 식별자 관계로 형성되어 있다. 그 상태에서 skip과 take 옵션을 넣어주게 되면 위와 같이 중복 제거를 위한 DISTINCT가 추가 되면서 내가 select 하지 않을 예정인 recipientId와 senderId를 찾을 수 없다는 에러가 발생한다. 해결 방법은 당연히 해당 PK들을 전부 select절에 추가 시켜주어야 한다. 그럼 만약 똑같은 find 메서드의 옵션에서 skip과 take를 빼고 요청하는 쿼리는 어떨까
skip과 take를 제외한 쿼리
SELECT ... 조회될 필드들 FROM "fam_notification" "NotificationEntity" LEFT JOIN "fam_member" "NotificationEntity__NotificationEntity_sender" ON "NotificationEntity__NotificationEntity_sender"."id"="NotificationEntity"."senderId" WHERE ("NotificationEntity"."recipientId" = $1)
내가 제일 처음 예상한 쿼리 그 잡채다.
결론
- find 메서드를 사용 할때에 paginate를 위해 skip과 take를 사용할때 식별관계인 테이블에서 사용시 주의해야 된다.
- 보통은 쿼리가 좀 더 복잡해지면 typeorm에서 쿼리빌더를 사용해버리는게 나을것 같다.
ps) 빨리 해당 프로젝트를 완성 한 후에 prisma를 해보고 싶다. prisma에서는 여러 관계들을 식별관계로 사용하는 칼럼에대해 어떻게 쿼리를 처리 할까 궁금하다
728x90'Nest.js > TypeOrm' 카테고리의 다른 글
TypeOrm과 js-joda를 이용한 Date타입 대신 LocalDateTime 타입 사용하기 (0) 2024.07.06 TypeOrm과 Postgresql에서 timestamp을 UpdateDateColumn 데코레이터 사용시 transformer 이슈 (0) 2024.07.06 @BeforInsert 와 @AfterInsert 사용시 주의할점 (0) 2024.05.02 NestJS에서 TypeOrm에서 쿼리로그 (0) 2024.04.22 TypeOrm에서 findOption의 order를 이용시 skip과 take의 paginate 오류 (0) 2024.01.25