Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] refactor: 특정 상품에 대한 리뷰 목록 조회 N+1 문제 완전히 해결 #838

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
import com.funeat.review.specification.SortingReviewSpecification;
import com.funeat.tag.domain.Tag;
import com.funeat.tag.persistence.TagRepository;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationEventPublisher;
Expand Down Expand Up @@ -184,10 +186,21 @@ private List<SortingReviewDto> getSortingReviews(final Member member, final Prod

private List<SortingReviewDto> addTagsToSortingReviews(
final List<SortingReviewDtoWithoutTag> sortingReviewDtoWithoutTags) {
return sortingReviewDtoWithoutTags.stream()
.map(reviewDto -> SortingReviewDto.toDto(reviewDto,
tagRepository.findTagsByReviewId(reviewDto.getId())))
final List<Long> reviewIds = sortingReviewDtoWithoutTags.stream()
.map(SortingReviewDtoWithoutTag::getId)
.collect(Collectors.toList());
final List<ReviewTag> reviewTags = reviewTagRepository.findReviewTagByReviewIds(reviewIds);

final List<SortingReviewDto> sortingReviewDtos = new ArrayList<>();
for (final SortingReviewDtoWithoutTag sortingReviewDtoWithoutTag : sortingReviewDtoWithoutTags) {
final List<Tag> tags = reviewTags.stream()
.filter(reviewTag -> Objects.equals(sortingReviewDtoWithoutTag.getId(), reviewTag.getReview().getId()))
.map(ReviewTag::getTag)
.collect(Collectors.toList());
final SortingReviewDto sortingReviewDto = SortingReviewDto.toDto(sortingReviewDtoWithoutTag, tags);
sortingReviewDtos.add(sortingReviewDto);
}
return sortingReviewDtos;
Comment on lines +194 to +203
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 효율적인 방법은 없을까요?
조회된 reviewTag 를 sortingReviewDtoWithoutTags 만큼 계속 돌 거 같아서요!! ㅎㅎ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이게 ReviewTag를 통해 ReviewTag를 서로 찾아 조립해주는 역할을 하는거라 저는 여기까지가 한계... ㅠㅠ
제가 보기엔 쿼리문을 덜 날리는 대신 메모리에서 더 처리하기 vs 쿼리문을 더 날려서 메모리에서 덜 처리하기라 저는 전자를 택했어요

전자) O(Review 수 * ReviewTag 수)로 메모리에서 처리하는 대신 쿼리문 14개에서 3개로 줄이기 (= 현재 PR 코드)
후자) O(Review 수)로 메모리는 덜 쓰고, 각 리뷰가 원하는 태그들을 쿼리문으로 날려서 디비에서 가져오기 (= 현재 프로덕션 코드)

}

private Specification<Review> getSortingSpecification(final Product product, final String sortOption,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface ReviewTagRepository extends JpaRepository<ReviewTag, Long> {

Expand All @@ -21,4 +22,11 @@ public interface ReviewTagRepository extends JpaRepository<ReviewTag, Long> {
void deleteByReview(final Review review);

List<ReviewTag> findByReview(final Review review);

@Query("SELECT rt "
+ "FROM ReviewTag rt "
+ "JOIN FETCH rt.review "
+ "JOIN FETCH rt.tag "
+ "WHERE rt.review.id IN :reviewIds")
List<ReviewTag> findReviewTagByReviewIds(@Param("reviewIds") final List<Long> reviewIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ public class ReviewSteps {
.cookie("SESSION", loginCookie)
.queryParam("sort", sort)
.queryParam("page", page)
.queryParam("lastReviewId", lastReviewId).log().all()
.queryParam("lastReviewId", lastReviewId)
.when()
.get("/api/products/{product_id}/reviews", productId)
.then().log().all()
.then()
.extract();
}

Expand All @@ -80,7 +80,7 @@ public class ReviewSteps {
return given()
.when()
.get("/api/ranks/products/{product_id}/reviews", productId)
.then().log().all()
.then()
.extract();
}

Expand Down