구현한 기능
- 매장 추천 API 개발 (평점, 예약 수, 리뷰 수 기준 정렬)
- 사용자 선호도에 따른 정렬 기준 선택 기능 (sortBy 파라미터)
- 결과 개수 제한 기능 (limit 파라미터)
- 각 매장의 평균 평점, 리뷰 수, 예약 수 정보 제공
코드 스냅샷
@GetMapping
public ResponseEntity<ApiResponse<List<StoreRecommendationDto.Response>>> getRecommendedStores(
@RequestParam(defaultValue = "rating") String sortBy,
@RequestParam(defaultValue = "10") Integer limit
) {
StoreRecommendationDto.RecommendationCriteria criteria = StoreRecommendationDto.RecommendationCriteria.builder()
.sortBy(sortBy)
.limit(limit)
.build();
List<StoreRecommendationDto.Response> recommendations =
storeRecommendationService.getRecommendedStores(criteria);
return ResponseEntity.ok(ApiResponse.success("인기 매장 목록을 성공적으로 조회했습니다.", recommendations));
}
@Transactional(readOnly = true)
public List<StoreRecommendationDto.Response> getRecommendedStores(StoreRecommendationDto.RecommendationCriteria criteria) {
String sortBy = criteria.getSortBy() != null ? criteria.getSortBy().toLowerCase() : "rating";
int limit = criteria.getLimit() != null ? criteria.getLimit() : 10;
List<Store> stores = storeRepository.findAllByActiveOrderByNameAsc(true);
List<StoreRecommendationDto.Response> recommendationResponses = stores.stream()
.map(store -> {
Long storeId = store.getId();
Double averageRating = reviewRepository.getAverageRatingByStoreId(storeId);
Long reviewCount = reviewRepository.countByStoreIdAndActive(storeId, true);
Long reservationCount = reservationRepository.countByStoreId(storeId);
if (averageRating == null) {
averageRating = 0.0;
}
return StoreRecommendationDto.Response.builder()
.storeId(storeId)
.name(store.getName())
.address(store.getAddress())
.description(store.getDescription())
.phoneNumber(store.getPhoneNumber())
.businessHours(store.getBusinessHours())
.averageRating(averageRating)
.reviewCount(reviewCount)
.reservationCount(reservationCount)
.latitude(store.getLatitude())
.longitude(store.getLongitude())
.build();
})
.collect(Collectors.toList());
switch (sortBy) {
case "reservation":
recommendationResponses.sort((a, b) -> b.getReservationCount().compareTo(a.getReservationCount()));
break;
case "review":
recommendationResponses.sort((a, b) -> b.getReviewCount().compareTo(a.getReviewCount()));
break;
case "rating":
default:
recommendationResponses.sort((a, b) -> b.getAverageRating().compareTo(a.getAverageRating()));
break;
}
return recommendationResponses.stream()
.limit(limit)
.collect(Collectors.toList());
}