SLQ, AdonisJS / 찜(좋아요)기능 쿼리짜기 (join and)

flobeeee·2022년 1월 16일
3

시행착오

목록 보기
28/45
post-thumbnail

💜 목적

여러 브랜드를 모아둔 쇼핑몰에서 찜하는 기능을 만들어보자.
유저는 쇼핑몰을 사용하면서 평소 자주 이용하는 브랜드를 찜할 수 있다.
유저는 사고싶은 상품들을 찜할 수 있다.


💜 테이블 구성

한 유저는 여러브랜드, 여러 제품을 찜할 수 있다.
한 브랜드 여러유저에게 찜을 받을 수 있다.
한 제품은 여러유저에게 찜을 받을 수 있다.
-> user와 brand, item을 이어주는 조인 테이블(user_like)이 필요하다.


💜 데이터 쌓기

user_like 테이블을 설명하자만
상어 유저는 코코밀크와 윈터춥춥 브랜드를 찜했습니다.
악어 유저는 코코밀크 브랜드를 찜했습니다.
호랑이 유저는 아무것도 찜하지 않았습니다.


💜 쿼리

브랜드 목록을 보여줄때, 유저의 입장에서 찜 유무를 보여줘야 합니다.
join에 and 조건을 붙여서 더 많은 제약을 걸어봤습니다.

brand 테이블 기준으로 user_like 테이블을 join 하는데,
brand.id 와 user_like.like_id 가 같아야 합니다.
user_like.user_id 가 해당 유저의 id와 같아야 합니다.
user_like.like_type이 brand 여야 합니다.
(item 찜 여부를 보려면 brand 대신 모두 item을 넣으면 됩니다.)

상어 유저(user.id = 1)의 데이터 입니다.

select 
brand.* , 
(user_like.user_id = 1 and like_type = 'brand') AS isLike 
from brand 
left join user_like on brand.id = user_like.like_id 
and user_like.user_id = 1 
and user_like.like_type = 'brand';

악어 유저(user.id = 2)의 데이터 입니다.

select 
brand.* , 
(user_like.user_id = 2 and like_type = 'brand') AS isLike 
from brand 
left join user_like on brand.id = user_like.like_id 
and user_like.user_id = 2 
and user_like.like_type = 'brand';

악어 유저는 윈터춥춥 브랜드를 찜하지 않아서 isLike 가 null로 나옵니다.

호랑이 유저(user.id = 3)의 데이터 입니다.

select 
brand.* , 
(user_like.user_id = 3 and like_type = 'brand') AS isLike 
from brand 
left join user_like on brand.id = user_like.like_id 
and user_like.user_id = 3 
and user_like.like_type = 'brand';

호랑이 유저는 찜한 브랜드가 없어서 isLike가 둘다 null로 나옵니다.


💜 adonisJS 프레임워크 예제

출처 : 공식문서(adonisJS join)

Database
  .from('users')
  .join('user_logins', (query) => {
    query
      .on('users.id', '=', 'user_logins.user_id')
      .andOnVal('user_logins.created_at', '>', '2020-10-09')
  })
  .select('users.*')
  .select('user_logins.ip_address')
  .select('user_logins.country')

실제 프로젝트에는 join에 두번째 인수를 받아서 .andOnval 을 사용해서 구현했다.


💜 후기

다양하게 쿼리문을 시도했었다.
수많은 시도 끝에도 원하는 데이터결과가 안나와서 팀원(사수)에게 도움을 요청하고 싶었다.
아 그래도 백엔드 개발자인데, 쿼리못짜서 징징대러 가는 내 자신을 참을 수 없었다.

짜다가 짜다가 안돼서 심호흡하고 왜 안되는지 생각해봤다.
가져올 데이터만 생각하고 어떤 방식으로 가져올지에 대해 깊은 생각은 하지 않았다는 것을 깨달았다.

left join을 해야했고, 찜을 했는지 안했는지에 대해 유무를 가지고 오고 싶었다.
join table에 해당 유저, 찜한 데이터의 id, 브랜드인지 상품인지 3가지의 조건이 맞아야했다.
그렇다. 나는 join에 조건문을 붙이고 싶었다. (명쾌!)

join에 and 조건이라니 사용한 적도 들어본 적도 없었다.
단순하게 join and 라고 구글링해보니 참고할만한 글이 많이 나왔다.
이렇게 쉽게 해결될걸..
그래도 시행착오를 겪었기 때문에, 여기까지 도달했다고 생각한다.

백엔드 개발자로서 레벨 1업을 했다고 생각한다.ㅎㅎ
지난 추석에 공부한 sql도 복습하고, 더 심화조건도 찾아봐야겠다.


💜보완 (2023.01.17)

select 
brand.* , 
-- (user_like.user_id = 1 and like_type = 'brand') AS isLike
(user_like.id) AS isLike 
from brand 
left join user_like on brand.id = user_like.like_id 
and user_like.user_id = 1 
and user_like.like_type = 'brand';

isLike 컬럼에 숫자가 있는 경우는 좋아요를 누른 거라고 판단합니다.
실제로는 조인테이블에 is_deleted 와 deleted_at 컬럼을 함께 넣어서
좋아요를 취소했다가 다시 눌러도 새로운 컬럼이 쌓이지 않게 설계했습니다.
id가 있고 is_deleted가 false인 경우 좋아요를 누른거라고 판단할 수 있습니다.

profile
기록하는 백엔드 개발자

2개의 댓글

comment-user-thumbnail
2023년 1월 2일

brand목록 like와 함께 조회할 때 쿼리 틀렸내요. 저렇게 조회하면 본인이 좋아요를 누른 brand만 조회할 수 있을 것입니다. 거기에 where절에서 이미 거른 userId 정보는 select절에서 다시 비교할 필요도 없죠.

1개의 답글