ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 코드로 정렬 vs db에서 특정 값을 정렬해서 select
    프로젝트/Trend-Pick 2023. 7. 28. 22:30

    사진 랭킹을 보여주는 페이지를 만들 때 dto로 사진 과 사진의 좋아요 개수를 넘겨줘야한다.

    처음에는 사진만 select 한 다음 service 계층에서 자바 코드로 로직을 구현했었다.

     

    하지만 좋아요 개수가 아니라 시간에 따른 좋아요 개수로 정렬해야하기 때문에 정렬을 할 때 db와의 소통이 무조건 필요했다. 많은 시간을 들인 끝에야 쿼리로 데이터를 받아오는 것이 맞다고 판단해서 repository 계층에서 select를 할 때 사진과 함께 사진의 좋아요 수를 쿼리로 받아왔다.

     

    주간 랭킹의 예시

    public List<Object[]> weeklyLike() {
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime startOfWeek = now.with(DayOfWeek.MONDAY);
            LocalDateTime endOfWeek = startOfWeek.plusDays(7);
    
            List<Object[]> resultList = em.createQuery(
                            "SELECT l.picture, " +
                                    "SUM(CASE WHEN l.status = :likeStatus THEN 1 " +
                                    "         WHEN l.status = :dislikeStatus THEN -1 " +
                                    "         ELSE 0 END) as likeDislikeDifference " +
                                    "FROM Like l " +
                                    "WHERE l.likeTime >= :startOfWeek " +
                                    "AND l.likeTime < :endOfWeek " +
                                    "GROUP BY l.picture.id " +
                                    "ORDER BY likeDislikeDifference DESC", Object[].class)
                    .setParameter("startOfWeek", startOfWeek)
                    .setParameter("endOfWeek", endOfWeek)
                    .setParameter("likeStatus", LikeStatus.LIKE)
                    .setParameter("dislikeStatus", LikeStatus.DISLIKE)
                    .setMaxResults(3)
                    .getResultList();
    
            return resultList;
        }

    이렇게 받아오고 return 값을 Object[] 배열로 반환했다.

     

     

     

    public List<Object[]> RankingOfWeek() {
        List<Object[]> weeklyLike = likeRepository.weeklyLike();
        return weeklyLike; 
    }

    Service 계층에서는 조회를 한 다음 컨트롤러로 넘겨주었다.

     

     

     

    @GetMapping("weekly_ranking")
    public List<WeeklyRankingDto> weeklyRanking() {
        List<Object[]> pictures = likeService.RankingOfWeek();
        List<WeeklyRankingDto> weeklyList = new ArrayList<>();
    
        for (Object[] result : pictures) {
            Picture picture = (Picture) result[0];
            Long likeDislikeDifference = (Long) result[1];
    
            Long pictureId = picture.getId();
            WeeklyRankingDto weeklyRankingDto = new WeeklyRankingDto(pictureId, likeDislikeDifference);
            weeklyList.add(weeklyRankingDto);
        }
        
        return weeklyList;
    }

    컨트롤러 계층에서 Service 계층의 RankingOfWeek를 불러와서 picutres라는 Object[] 타입의 리스트로 받아왔다.

    그리고 for문을 통해 result의 첫번째 값 (result[0])은 picutre로, reuslt의 두번째 값 (result[1])은 좋아요의 수로 형변환을 시켜준 뒤 dto의 리스트에 하나씩 넣어주고, 그 리스트를 반환했다.

     

     

     

     

    값을 가져오거나 정렬할 때에 자바 코드로 하는 것이 더 나은 선택인지, 쿼리를 통해 특정 값을 가져오는 것이 효율적인지 정하는 것이 중요하다.

    이번에는 좋아요를 누른 시간에 따라서 달라졌다.

    만약에 A라는 사진의 누적 좋아요 수가 100개인데, 그 중에서 이번 주에 받은 좋아요 수인 50개만 가져와야 하니까 db에서 특정 값을 가져오는 것이 훨씬 효율적이라는 것을 알게 되었다.

Designed by Tistory.