Post

맛집 평점 업데이트 구현하기: 평균값 구하기

240902 TIL

맛집 평점 업데이트 구현하기: 평균값 구하기

✨ 맛집 평점 업데이트 구현하기: 평균값 구하기

허무함주의

문제

1
2
3
4
5
6
7
8
  private async updateRestaurantRating(id: string): Promise<void> {
	
    // 여기 들어갈 로직

    // 소수점 한 자리만 나오도록
    const updatedRating = (sum / count).toFixed(1);
    this.restaurantRepository.update({ id: id }, { rating: +updatedRating });
  }
  • 리뷰 생성 API에서 호출할 맛집 평점 업데이트 함수이다.
  • 평균을 계산하기 위해 합계(SUM)와 전체 레코드 수(COUNT)가 필요했다.
  • 팀 컨벤션이 Repository API를 우선시하는거라 어떻게 해야하나 고민이었다.

방법s

  1. 일단 COUNT 하고 코드단에서 SUM을 구하는 방법
    1
    2
    3
    4
    5
    
       const [reviews, count] = await this.reviewRepository.findAndCount({
       select: ['rating'],
       where: { id },
     });
     const sumOfRatings = reviews.reduce((acc, cur) => (acc += cur.rating), 0);
    
    • findAndCount()는 조건에 맞는 레코드들과 총 레코드 수를 반환한다.
    • 배열 순회 메서드인 reduce()를 활용해 각 리뷰 레코드의 rating만 더해 합계를 구한다.
  2. count()sum() 메서드를 각각 따로 호출해서 쓰는 방법
    • 1번 방법이 더 나아보여서 코드를 짜진 않았다.
  3. QueryBuilder를 사용하는 방법
    1
    2
    3
    4
    5
    6
    7
    8
    
      const { sum, count } = (
       await this.reviewRepository
         .createQueryBuilder('review')
         .select('COUNT(*) as count, SUM(rating) as sum')
         .where('review.restaurantId = :id', { id })
         .groupBy('review.restaurantId')
         .execute()
     )[0];
    
    • 엔티티를 가져오는게 아니기 때문에 getMany()가 아닌 execute()를 사용한다. SELECT한 결과는 0번째 인덱스로 온다.
    • DB에서 할 수 있는 건 DB에서 하자! 라는 마음으로 QueryBuilder를 사용하는 걸로 스스로 결론냈었는데…

결론

1
2
3
4
5
6
7
8
  // 맛집의 모든 리뷰 기록을 조회하고, 평균을 계산하여 평점을 업데이트 합니다.
  private async updateRestaurantRating(id: string): Promise<void> {
    const averageOfRatings = await this.reviewRepository.average('rating', { restaurantId: id });
    // 소수점 한 자리까지만 나오도록
    const updatedRating = +averageOfRatings.toFixed(1);

    this.restaurantRepository.update({ id }, { rating: updatedRating });
  }

팀 회의에서 위 내용의 TIL 리뷰를 하고… 팀원분께서 알려주신 내용

  • average()라는 Repository API가 있었다.
  • 사용해본 기억도 있는데 저 순간엔 아무런 생각도 나지 않았다. ㄱ-
  • 근데… 더 찾아봤으면 분명히 찾았을텐데… 나에게 약간 실망하엿음.ㅋ 문서 꼼꼼히 읽기~!

참고

This post is licensed under CC BY 4.0 by the author.