diff --git a/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java b/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java index 237e03e..13d39a9 100644 --- a/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java +++ b/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java @@ -37,12 +37,10 @@ public interface CardRepository extends JpaRepository { @Query(""" SELECT DISTINCT c FROM Card c -JOIN FETCH c.user u -LEFT JOIN FETCH c.cardHashtags ch WHERE c.isDeleted = false AND c.isShared = true - AND u.id <> :loginUserId - AND u.id NOT IN ( + AND c.user.id <> :loginUserId + AND c.user.id NOT IN ( SELECT ub.blockedUser.id FROM UserBlock ub WHERE ub.user.id = :loginUserId @@ -102,4 +100,14 @@ SELECT COUNT(c) """) Long countCardsByHashtag(@Param("hashtagId") Long hashtagId); + @Query(""" + SELECT ch.hashtag.id, COUNT(ch.card.id) + FROM CardHashtag ch + WHERE ch.hashtag.id IN :hashtagIds + AND ch.card.isDeleted = false + AND ch.card.isShared = true + GROUP BY ch.hashtag.id + """) + List countCardsByHashtagIds(@Param("hashtagIds") List hashtagIds); + } \ No newline at end of file diff --git a/src/main/java/EatPic/spring/domain/card/service/SearchServiceImpl.java b/src/main/java/EatPic/spring/domain/card/service/SearchServiceImpl.java index a1e6a13..b56be23 100644 --- a/src/main/java/EatPic/spring/domain/card/service/SearchServiceImpl.java +++ b/src/main/java/EatPic/spring/domain/card/service/SearchServiceImpl.java @@ -127,24 +127,8 @@ public SearchResponseDTO.GetHashtagListResponseDto getHashtagInAll(HttpServletRe Pageable pageable = PageRequest.of(0, limit + 1, Sort.by("id").ascending()); Slice hashtags = hashtagRepository.searchHashtagInAll("%" + query + "%", cursor, pageable); - List result = hashtags.getContent().stream() - .map(hashtag -> CardConverter.toHashtagDto( - hashtag, - cardRepository.countCardsByHashtag(hashtag.getId()) - )) - .filter(dto -> dto.getCard_count() > 0) // 카드가 없는 해시태그는 제외 - .toList(); - - if (result.isEmpty()) { - throw new ExceptionHandler(ErrorStatus._NO_RESULTS_FOUND); - - } - boolean hasNext = hashtags.hasNext(); - Long nextCursor = hasNext ? hashtags.getContent().get(hashtags.getContent().size() - 1).getId() : null; - - return new SearchResponseDTO.GetHashtagListResponseDto(result, nextCursor, result.size(), hasNext); + return getGetHashtagListResponseDto(hashtags); } - // 유저가 팔로우한 사용자인 경우에서 해시태그 검색 @Override public SearchResponseDTO.GetHashtagListResponseDto getHashtagInFollow(HttpServletRequest request, String query, int limit, Long cursor) { @@ -158,27 +142,34 @@ public SearchResponseDTO.GetHashtagListResponseDto getHashtagInFollow(HttpServle } Pageable pageable = PageRequest.of(0, limit + 1, Sort.by("id").ascending()); - Slice hashtags = hashtagRepository.searchHashtagInFollow(query, followingUserIds, cursor, pageable); + return getGetHashtagListResponseDto(hashtags); + } + + private SearchResponseDTO.GetHashtagListResponseDto getGetHashtagListResponseDto(Slice hashtags) { + List hashtagsIds = hashtags.stream().map(Hashtag::getId).toList(); + Map cardCountByHashtagMap = getMapCardCountByHashtag(hashtagsIds); + List result = hashtags.getContent().stream() .map(hashtag -> CardConverter.toHashtagDto( hashtag, - cardRepository.countCardsByHashtag(hashtag.getId()) + cardCountByHashtagMap.getOrDefault(hashtag.getId(),0L) )) - .filter(dto -> dto.getCard_count() > 0) + .filter(dto -> dto.getCard_count() > 0) // 카드가 없는 해시태그는 제외 .toList(); if (result.isEmpty()) { throw new ExceptionHandler(ErrorStatus._NO_RESULTS_FOUND); - } + } boolean hasNext = hashtags.hasNext(); Long nextCursor = hasNext ? hashtags.getContent().get(hashtags.getContent().size() - 1).getId() : null; return new SearchResponseDTO.GetHashtagListResponseDto(result, nextCursor, result.size(), hasNext); } + // 해시태그 선택 시 해당 해시태그가 포함된 픽카드 리스트 조회 @Override public SearchResponseDTO.GetCardListResponseDto getCardsByHashtag(HttpServletRequest request, Long hashtagId, int limit, Long cursor) { @@ -188,10 +179,14 @@ public SearchResponseDTO.GetCardListResponseDto getCardsByHashtag(HttpServletReq Pageable pageable = PageRequest.of(0, limit + 1, Sort.by("id").ascending()); Slice cards = cardRepository.findCardsByHashtag(hashtagId, cursor, pageable); + List cardIds = cards.stream().map(Card::getId).toList(); + Map commentCountMap = cardService.getCommentCountMap(cardIds); + Map reactionCountMap = cardService.getReactionCountMap(cardIds); + List content = cards.getContent().stream() .map(card -> { - int commentCount = commentRepository.countByCardId(card.getId()); - int reactionCount = reactionRepository.countByCardId(card.getId()); + int commentCount = commentCountMap.getOrDefault(card.getId(), 0); + int reactionCount = reactionCountMap.getOrDefault(card.getId(), 0); return CardConverter.toCardResponseDto(card, commentCount, reactionCount); }) .toList(); @@ -205,4 +200,12 @@ public SearchResponseDTO.GetCardListResponseDto getCardsByHashtag(HttpServletReq return new SearchResponseDTO.GetCardListResponseDto(content, nextCursor, content.size(), hasNext); } + + private Map getMapCardCountByHashtag(List hashtagIds){ + List counts = cardRepository.countCardsByHashtagIds(hashtagIds); + return counts.stream().collect(Collectors.toMap( + row -> (Long) row[0], // hashtagId + row -> (Long) row[1] // count + )); + } } \ No newline at end of file