맛집 평점 업데이트 구현하기: 평균값 구하기
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
- 일단 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
만 더해 합계를 구한다.
count()
와sum()
메서드를 각각 따로 호출해서 쓰는 방법- 1번 방법이 더 나아보여서 코드를 짜진 않았다.
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.