Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

게시글 검색 최신순, 인기순 #447

Merged
merged 15 commits into from
May 8, 2024

Conversation

oxix97
Copy link
Collaborator

@oxix97 oxix97 commented Apr 29, 2024

개요

새로 게시글 검색 (인기순) API를 작성하지 않고 기존 로직에 수정을 하였습니다.

Controller

(require = false) Integer likeCount를 Param값으로 추가적으로 받습니다.

Service

-> lastLikeCount == null 인 경우 최신순으로 정렬(ID 내림차순)
-> lastLikeCount != null 인 경우 �좋아요 순으로 정렬 (좋아요 순 내림차순, ID 내림 차순)

�Reader

-> cursor == 0 인 경우 정렬 기준에 맞게 최대 10개 가져옴
-> cursor != 0 인 경우 커서보다 작은 ID를 정렬 기준에 맞게 가져옴

closed #437

PR 유형

어떤 변경 사항이 있나요?

  • 새로운 기능 추가
  • 버그 수정
  • CSS 등 사용자 UI 디자인 변경
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 테스트 추가, 테스트 리팩토링
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제
  • 배포 및 PR 관련

PR Checklist

PR이 다음 요구 사항을 충족하는지 확인하세요.

  • 커밋 메시지 컨벤션에 맞게 작성했습니다. Commit message convention 참고.
  • 변경 사항에 대한 테스트를 했습니다.(버그 수정/기능에 대한 테스트).

oxix97 added 7 commits April 29, 2024 13:01
LikeCount 값이 null 이 아닌 경우 : 인기순으로 검색된 내용 조회
LikeCount 값이 null 인 경우 : 최신순으로 검색된 내용 조회
like Count 유무에 따른 최신순 / 인기순 분기처리
@oxix97 oxix97 added 💻 BE 백엔드 🔨 Refactor 코드를 리팩토링한 경우 labels Apr 29, 2024
@oxix97 oxix97 self-assigned this Apr 29, 2024
return (cursor.equals(NumberConstants.FIRST_CURSOR))
? postRepository.findByTitleContainingOrContentContainingOrderByIdDesc(searchWord, searchWord, pageable)
? postRepository.findByTitleContainingOrContentContainingOrderByLikeCountDesc(searchWord, pageable)
: postRepository.findByLikeCountLessThanAndTitleContainingOrLikeCountLessThanAndContentContainingOrderByLikeCountDesc(likeCount, searchWord, likeCount, searchWord, pageable);
Copy link
Collaborator

@GBGreenBravo GBGreenBravo Apr 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 로직에 cursor로 들어오는 id도 고려돼야하지 않을까요?
예를 들어 검색어를 포함하고 "좋아요 5개 눌린" 게시글이 13개고, 10개가 조회된다면
다음에는 나머지 3개가 조회되고 좋아요 4개 이하를 탐색해야 하지만,
현재의 코드에서는 위 예시의 3개 게시글이 누락되는 상황이 발생할 것으로 예상됩니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요 5개 이하, 다음 커서로 조회 하면 나머지 3개 포함해서 출력되지 않나요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우선 지금 코드에서 좋아요수 이하가 아닌 미만으로 설정돼 있습니다. 이하로 하시려면 LessThan 뒤에 Equal 붙이셔야 해요~

그리고 나머지 3개는 현재 커서 기준(좋아요수)으로는 탐색이 아마 안 될 겁니다..! api 요청해보시면 아마 확인하실 수 있을 거에요!
findBy
LikeCountLessThanEqualAndTitleContaining
Or
LikeCountLessThanEqualAndContentContaining
OrderByLikeCountDesc
이렇게 Equal 붙여서 구현돼 있더라도 이전에 조회한 결과랑 똑같은 10개를 가져오고, 나머지 3개는 조회가 안 될 겁니다..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음..그렇네요 이런 케이스는 어떻게 처리하지..?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고유값이 없기 때문에 좋아요 검색에 한해서는 페이지당 게시글 갯수제한을 없애는것말곤...잘 떠오르질 않네요

Copy link
Collaborator

@GBGreenBravo GBGreenBravo Apr 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

페이지네이션을 안 한다면 뭔가 컨벤션이 복잡해져서 저희 측에서 구현하는 게 맞을 듯 합니다..!
아직도 정복하지 못한 QueryDsl 이슈를 회피해서 최대한 쥐어짜내보면, 아래와 같은 방식으로 구현가능할 듯 합니다.

FirstCursor인 경우에 ->
기존의 findByTitleContainingOrContentContainingOrderByLikeCountDesc 뒤에 CreatedAtDesc를 추가해서
findByTitleContainingOrContentContainingOrderByLikeCountDescCreatedAtDesc로 구현하여, 좋아요수가 같은 경우는 최신순으로 정렬하도록 세팅.

FirstCursor가 아닌 경우에 ->
(1) cursor(마지막으로 조회한 게시글 id) 게시글의 좋아요 수와 같은 좋아요 수를 가진 posts 우선 조회
-findBy TitleContainingAndLikeCountEquals Or ContentContainingAndLikeCountEquals OrderByCreatedAtDesc

(2-1) 1번에서 조회된 posts의 개수가 POST_PAGINATION_SIZE와 같으면 posts 바로 return

(2-2) 1번에서 조회된 posts의 개수가 POST_PAGINATION_SIZE 미만이면, 그만큼 PageRequest의 사이즈를 줄여서 현재 좋아요수 미만의 조회 실행
-findBy LikeCountLessThanAndTitleContaining Or LikeCountLessThanAndContentContaining OrderByLikeCountDescCreatedAtDesc
후 1의 결과물과 병합하여 return

@kkkapuq kkkapuq requested a review from c0olcode April 30, 2024 08:48
return (cursor.equals(NumberConstants.FIRST_CURSOR))
? postRepository.findByTitleContainingOrContentContainingOrderByIdDesc(searchWord, searchWord, pageable)
? postRepository.findByTitleContainingOrContentContainingOrderByLikeCountDesc(searchWord, pageable)
: postRepository.findByLikeCountLessThanAndTitleContainingOrLikeCountLessThanAndContentContainingOrderByLikeCountDesc(likeCount, searchWord, likeCount, searchWord, pageable);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음..그렇네요 이런 케이스는 어떻게 처리하지..?

return (cursor.equals(NumberConstants.FIRST_CURSOR))
? postRepository.findByTitleContainingOrContentContainingOrderByIdDesc(searchWord, searchWord, pageable)
? postRepository.findByTitleContainingOrContentContainingOrderByLikeCountDesc(searchWord, pageable)
: postRepository.findByLikeCountLessThanAndTitleContainingOrLikeCountLessThanAndContentContainingOrderByLikeCountDesc(likeCount, searchWord, likeCount, searchWord, pageable);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고유값이 없기 때문에 좋아요 검색에 한해서는 페이지당 게시글 갯수제한을 없애는것말곤...잘 떠오르질 않네요

Comment on lines 66 to 67
PageRequest.of(cursor.intValue(), POST_PAGINATION_SIZE, Sort.by(Sort.Order.desc("likeCount"), Sort.Order.desc("createdAt")))
: PageRequest.of(cursor.intValue(), POST_PAGINATION_SIZE, Sort.by(Sort.Order.desc("createdAt")));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cursor.intValue를 PageRequest에 담으면 비정상적으로 조회되지 않나요?
커서가 페이지 번호를 의미하는 게 아니라 마지막으로 조회된 게시글의 id를 가져온 거라, 예상과 다르게 동작할 것으로 예측합니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cursor에다가 페이지 번호를 0부터 담으면 정상적으로 작동하는거 같은데, 혹시 이전 코드에서 cursor가 어떤 의미 역할을 맡고 있었나요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

페이지네이션 방식의 차이로 보입니다! 다른 페이지네이션에서의 커서는 전부 조회된 목록에서 가장 마지막으로 조회한 게시글/암장/댓글의 id를 받고 있었습니다. 해당 링크 참고하시면 도움될 듯 합니다.

그런데 이렇게 바뀌는 거라면, 프론트에서 전달하는 값도 달라지기 때문에 프론트와 협의가 필요하고,
추가로 구분을 위해서 파라미터명도 cursor -> page로의 변경도 필요할 듯 합니다!

oxix97 added 3 commits May 8, 2024 18:15
null이 아닌 정수형의 likeCount가 있으면 인기순 조회라는 가정으로 수정
@oxix97 oxix97 requested review from kkkapuq and GBGreenBravo May 8, 2024 09:28
Comment on lines 36 to 40
@Query("SELECT p FROM post p WHERE LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%') ORDER BY p.likeCount DESC, p.id DESC")
List<Post> findBySearchWordOrderByLikeCountDesc(String keyword, Pageable pageable);

@Query("SELECT p FROM post p WHERE (LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%')) AND (p.likeCount < :likeCount OR (p.likeCount = :likeCount AND p.id < :cursor)) ORDER BY p.likeCount DESC, p.id DESC")
List<Post> findBySearchWordOrderByLikeCountDescWithCursor(String keyword, Long cursor, int likeCount, Pageable pageable);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요게 핵심인것같은데, 인기순으로 정렬하고, 좋아요 수가 동일하다면 최신순으로 내부 정렬시킨다음, 그 커서값을 기준으로 다음 페이지를 조회하는 건가요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

가독성 높이기 위해서 아래처럼 줄바꿈하는 건 어떨까요?

SELECT p
FROM post p
WHERE (LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%'))
AND (p.likeCount < :likeCount OR (p.likeCount = :likeCount AND p.id < :cursor))
ORDER BY p.likeCount DESC, p.id DESC

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

형준님이 말씀하신게 정확합니다

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

줄바꿈 바로 반영합니다~

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 가독성땜시 민협님 의견에 찬성합니다람쥐

Comment on lines 36 to 40
@Query("SELECT p FROM post p WHERE LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%') ORDER BY p.likeCount DESC, p.id DESC")
List<Post> findBySearchWordOrderByLikeCountDesc(String keyword, Pageable pageable);

@Query("SELECT p FROM post p WHERE (LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%')) AND (p.likeCount < :likeCount OR (p.likeCount = :likeCount AND p.id < :cursor)) ORDER BY p.likeCount DESC, p.id DESC")
List<Post> findBySearchWordOrderByLikeCountDescWithCursor(String keyword, Long cursor, int likeCount, Pageable pageable);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

가독성 높이기 위해서 아래처럼 줄바꿈하는 건 어떨까요?

SELECT p
FROM post p
WHERE (LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%'))
AND (p.likeCount < :likeCount OR (p.likeCount = :likeCount AND p.id < :cursor))
ORDER BY p.likeCount DESC, p.id DESC

Copy link
Collaborator

@kkkapuq kkkapuq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 어떻게 짜야될지 막막했는데 이런식으로 풀어주셨군요 감사합니다

Comment on lines 36 to 40
@Query("SELECT p FROM post p WHERE LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%') ORDER BY p.likeCount DESC, p.id DESC")
List<Post> findBySearchWordOrderByLikeCountDesc(String keyword, Pageable pageable);

@Query("SELECT p FROM post p WHERE (LOWER(p.title) LIKE CONCAT('%',LOWER(:keyword),'%') OR LOWER(p.content) LIKE CONCAT('%',LOWER(:keyword),'%')) AND (p.likeCount < :likeCount OR (p.likeCount = :likeCount AND p.id < :cursor)) ORDER BY p.likeCount DESC, p.id DESC")
List<Post> findBySearchWordOrderByLikeCountDescWithCursor(String keyword, Long cursor, int likeCount, Pageable pageable);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 가독성땜시 민협님 의견에 찬성합니다람쥐

@oxix97 oxix97 merged commit b2f7196 into Kernel360:develop May 8, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💻 BE 백엔드 🔨 Refactor 코드를 리팩토링한 경우
Projects
None yet
Development

Successfully merging this pull request may close these issues.

게시글 검색 리팩터링 - 인기순(좋아요), 최신순(글 생성시간)
3 participants