Skip to content

Commit

Permalink
feat : 강의 목록 API 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
JunHwan Kim committed Jan 4, 2024
1 parent fa0b980 commit f24783e
Show file tree
Hide file tree
Showing 25 changed files with 286 additions and 164 deletions.
2 changes: 1 addition & 1 deletion src/main/java/dnd/project/domain/BaseEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public abstract class BaseEntity {
private LocalDateTime createdDate;

@PrePersist
public void onPrePersist(){
public void onPrePersist() {
this.createdDate = LocalDateTime.now(ZoneId.of("Asia/Seoul"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
@Repository
public interface BookmarkRepository extends JpaRepository<Bookmark, Long>, BookmarkCustomRepository {
Optional<Bookmark> findByLectureAndUser(Lecture lecture, Users user);

void deleteByLectureAndUser(Lecture lecture, Users users);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import com.querydsl.core.types.dsl.StringExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import dnd.project.domain.lecture.entity.Lecture;
import dnd.project.domain.lecture.response.LectureListReadResponse;
import dnd.project.domain.lecture.response.LectureReviewListReadResponse;
import dnd.project.domain.lecture.response.LectureScopeListReadResponse;
import dnd.project.domain.review.entity.Review;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -51,6 +53,45 @@ public Map<Long, Long> findBookmarkCount(List<Long> ids) {
.transform(GroupBy.groupBy(lecture.id).as(bookmark.id.count()));
}

public Map<Long, Double> findReviewAverageScore(List<Long> ids) {
return queryFactory
.from(lecture)
.leftJoin(review).on(lecture.id.eq(review.lecture.id))
.where(lecture.id.in(ids))
.groupBy(lecture.id)
.transform(GroupBy.groupBy(lecture.id).as(review.score.avg()));
}

public List<Review> findAllReviewsByIds(List<Long> ids) {
return queryFactory
.select(review)
.from(review)
.where(review.lecture.id.in(ids))
.fetch();
}


public List<LectureListReadResponse.LectureInfo.ReviewInfo> findAllReviewsById(Long id) {

return queryFactory.select(
Projections.constructor(LectureListReadResponse.LectureInfo.ReviewInfo.class,
review.id,
selectUser("nickName"),
review.tags,
review.content,
review.createdDate,
review.score,
likeReview.id.count()))
.from(review)
.leftJoin(review.user, users)
.leftJoin(likeReview).on(review.id.eq(likeReview.review.id))
.where(review.lecture.id.eq(id))
.groupBy(review.id)
.orderBy(review.id.desc())
.limit(10)
.fetch();
}

public Page<Lecture> findAll(String mainCategory,
String subCategory,
String searchKeyword,
Expand Down Expand Up @@ -198,6 +239,7 @@ public List<String> findAllReviewTagsById(Long id) {
.fetch();
}


public Page<LectureReviewListReadResponse.ReviewInfo> findAllReviewsById(Long id,
String searchKeyword,
Integer page,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package dnd.project.domain.lecture.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import dnd.project.domain.lecture.entity.Lecture;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Getter
Expand All @@ -30,8 +33,16 @@ public static class LectureInfo {
private final String imageUrl;
private final Long reviewCount;
private final Long bookmarkCount;
private final Double averageScore;
private final List<TagGroup> tagGroups;
private final List<ReviewInfo> reviews; // 최근 10개 리뷰

public static LectureInfo of(Lecture lecture, Long reviewCount, Long bookmarkCount) {
public static LectureInfo of(Lecture lecture,
Long reviewCount,
Long bookmarkCount,
Double averageScore,
List<TagGroup> tagGroups,
List<ReviewInfo> reviews) {
return new LectureInfo(lecture.getId(),
lecture.getTitle(),
lecture.getSource(),
Expand All @@ -42,7 +53,34 @@ public static LectureInfo of(Lecture lecture, Long reviewCount, Long bookmarkCou
lecture.getSubCategory(),
lecture.getImageUrl(),
reviewCount,
bookmarkCount);
bookmarkCount,
averageScore,
tagGroups,
reviews);
}

@Getter
public static class ReviewInfo {
private final Long id;
private final String nickname;
private final List<String> tags = new ArrayList<>();
private final String content;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
private final LocalDateTime createdDate;
private final Double score;
private final Long likeCount;

public ReviewInfo(Long id, String nickname, String tags, String content, LocalDateTime createdDate, Double score, Long likeCount) {
this.id = id;
this.nickname = nickname;
for (String tag : tags.split(",")) {
this.tags.add(tag.trim());
}
this.content = content;
this.createdDate = createdDate;
this.score = score;
this.likeCount = likeCount;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,4 @@ public static LectureReadResponse of(Lecture lecture,
averageScore,
tagGroups);
}

@Getter
@RequiredArgsConstructor
public static class TagGroup {
private final String name;
private final List<Tag> tags;

@Getter
@RequiredArgsConstructor
public static class Tag {
private final String name;
private final Integer count;
}
}
}
20 changes: 20 additions & 0 deletions src/main/java/dnd/project/domain/lecture/response/TagGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dnd.project.domain.lecture.response;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.List;

@Getter
@RequiredArgsConstructor
public class TagGroup {
private final String name;
private final List<Tag> tags;

@Getter
@RequiredArgsConstructor
public static class Tag {
private final String name;
private final Integer count;
}
}
136 changes: 64 additions & 72 deletions src/main/java/dnd/project/domain/lecture/service/LectureService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
import dnd.project.domain.lecture.entity.LectureCategory;
import dnd.project.domain.lecture.repository.LectureQueryRepository;
import dnd.project.domain.lecture.repository.LectureRepository;
import dnd.project.domain.lecture.response.LectureListReadResponse;
import dnd.project.domain.lecture.response.LectureReadResponse;
import dnd.project.domain.lecture.response.LectureReviewListReadResponse;
import dnd.project.domain.lecture.response.LectureScopeListReadResponse;
import dnd.project.domain.lecture.response.*;
import dnd.project.domain.review.entity.Review;
import dnd.project.domain.review.entity.ReviewTag;
import dnd.project.domain.user.entity.Users;
import dnd.project.domain.user.repository.UserRepository;
Expand All @@ -31,6 +29,15 @@ public class LectureService {
private static final Integer LECTURE_REVIEW_MAX_SIZE = 10;
private static final Integer LECTURE_REVIEW_DEFAULT_SIZE = 5;
private static final Integer LECTURE_REVIEW_MIN_SIZE = 1;
private static final Set<String> TAG_TYPES = Arrays.stream(ReviewTag.values())
.map(ReviewTag::getType)
.collect(Collectors.toSet());
private static final List<String> TAG_NAMES = Arrays.stream(ReviewTag.values())
.map(ReviewTag::getName)
.toList();
private static final Map<String, String> TAG_NAME_TYPES = Arrays.stream(ReviewTag.values()).
collect(Collectors.toMap(ReviewTag::getName,
ReviewTag::getType));

private final LectureQueryRepository lectureQueryRepository;
private final LectureRepository lectureRepository;
Expand All @@ -47,27 +54,19 @@ public LectureReadResponse getLecture(Long id) {
Double averageScore = lectureQueryRepository.findReviewAverageScoreById(id);
Double roundedAverageScore = Math.round(averageScore * 2) / 2.0;

// tagType 리스트
Set<String> tagTypes = Arrays.stream(ReviewTag.values())
.map(ReviewTag::getType)
.collect(Collectors.toSet());
// 전체 태그를 "," 로 구분 하여 자르고 각 키워드 별 카운트
List<String> tagsList = lectureQueryRepository.findAllReviewTagsById(id);

// tagName 리스트
List<String> tagNames = Arrays.stream(ReviewTag.values())
.map(ReviewTag::getName)
.toList();
List<TagGroup> tagGroups = getTagGroups(tagsList);

// (Key:tagName, Value:tagType)인 Map
Map<String, String> tagNameTypeMap = Arrays.stream(ReviewTag.values()).
collect(Collectors.toMap(ReviewTag::getName,
ReviewTag::getType));
return LectureReadResponse.of(lecture, reviewCount, roundedAverageScore, tagGroups);
}

// 전체 태그를 "," 로 구분하여 자르고 각 키워드 별 카운트
List<String> tagsList = lectureQueryRepository.findAllReviewTagsById(id);
private List<TagGroup> getTagGroups(List<String> tagsList) {

// 카운트 0 초기화
Map<String, Integer> tagCountMap = new HashMap<>();
for (String tagName : tagNames) {
for (String tagName : TAG_NAMES) {
tagCountMap.put(tagName, 0);
}

Expand All @@ -79,27 +78,20 @@ public LectureReadResponse getLecture(Long id) {
}
}

Map<String, List<LectureReadResponse.TagGroup.Tag>> result = new HashMap<>();

for (String tagType : tagTypes) {
result.put(tagType, new ArrayList<>());
}
Map<String, List<TagGroup.Tag>> result = new HashMap<>();

for (Map.Entry<String, Integer> entry : tagCountMap.entrySet()) {
String tagName = entry.getKey();
Integer tagCount = entry.getValue();
String tagType = tagNameTypeMap.get(tagName);
if (tagType != null && result.containsKey(tagType)) {
result.get(tagType).add(new LectureReadResponse.TagGroup.Tag(tagName, tagCount));
}
String tagType = TAG_NAME_TYPES.get(tagName);

result.computeIfAbsent(tagType, k -> new ArrayList<>())
.add(new TagGroup.Tag(tagName, tagCount));
}

List<LectureReadResponse.TagGroup> tagGroups = result.entrySet().stream()
.map(response ->
new LectureReadResponse.TagGroup(response.getKey(), response.getValue()))
return result.entrySet().stream()
.map(response -> new TagGroup(response.getKey(), response.getValue()))
.toList();

return LectureReadResponse.of(lecture, reviewCount, roundedAverageScore, tagGroups);
}

@Transactional(readOnly = true)
Expand Down Expand Up @@ -202,19 +194,7 @@ private LectureListReadResponse getLecturesFromMainSubCategory(Integer mainCateg

Page<Lecture> lectures = lectureQueryRepository.findAll(mainCategoryName, subCategoryName, searchKeyword, page, size, sort);

List<Long> ids = lectures.getContent().stream()
.map(Lecture::getId)
.toList();

Map<Long, Long> reviewCount = lectureQueryRepository.findReviewCount(ids);
Map<Long, Long> bookmarkCount = lectureQueryRepository.findBookmarkCount(ids);

List<LectureListReadResponse.LectureInfo> content = lectures.getContent().stream()
.map(lecture -> LectureListReadResponse.LectureInfo.of(
lecture,
reviewCount.getOrDefault(lecture.getId(), 0L),
bookmarkCount.getOrDefault(lecture.getId(), 0L)))
.collect(Collectors.toList());
List<LectureListReadResponse.LectureInfo> content = getLectureInfos(lectures);

int totalPages = lectures.getTotalPages();
long totalElements = lectures.getTotalElements();
Expand All @@ -234,19 +214,7 @@ private LectureListReadResponse getLecturesFromMainCategory(Integer mainCategory

Page<Lecture> lectures = lectureQueryRepository.findAll(mainCategoryName, null, searchKeyword, page, size, sort);

List<Long> ids = lectures.getContent().stream()
.map(Lecture::getId)
.toList();

Map<Long, Long> reviewCount = lectureQueryRepository.findReviewCount(ids);
Map<Long, Long> bookmarkCount = lectureQueryRepository.findBookmarkCount(ids);

List<LectureListReadResponse.LectureInfo> content = lectures.getContent().stream()
.map(lecture -> LectureListReadResponse.LectureInfo.of(
lecture,
reviewCount.getOrDefault(lecture.getId(), 0L),
bookmarkCount.getOrDefault(lecture.getId(), 0L)))
.collect(Collectors.toList());
List<LectureListReadResponse.LectureInfo> content = getLectureInfos(lectures);

int totalPages = lectures.getTotalPages();
long totalElements = lectures.getTotalElements();
Expand All @@ -263,19 +231,7 @@ private LectureListReadResponse getLecturesFromAllCategory(String searchKeyword,

Page<Lecture> lectures = lectureQueryRepository.findAll(null, null, searchKeyword, page, size, sort);

List<Long> ids = lectures.getContent().stream()
.map(Lecture::getId)
.toList();

Map<Long, Long> reviewCount = lectureQueryRepository.findReviewCount(ids);
Map<Long, Long> bookmarkCount = lectureQueryRepository.findBookmarkCount(ids);

List<LectureListReadResponse.LectureInfo> content = lectures.getContent().stream()
.map(lecture -> LectureListReadResponse.LectureInfo.of(
lecture,
reviewCount.getOrDefault(lecture.getId(), 0L),
bookmarkCount.getOrDefault(lecture.getId(), 0L)))
.collect(Collectors.toList());
List<LectureListReadResponse.LectureInfo> content = getLectureInfos(lectures);

int totalPages = lectures.getTotalPages();
long totalElements = lectures.getTotalElements();
Expand All @@ -285,6 +241,42 @@ private LectureListReadResponse getLecturesFromAllCategory(String searchKeyword,
return LectureListReadResponse.of(totalPages, pageNumber, pageSize, totalElements, content);
}

private List<LectureListReadResponse.LectureInfo> getLectureInfos(Page<Lecture> lectures) {
List<Long> ids = lectures.getContent().stream()
.map(Lecture::getId)
.toList();

Map<Long, Long> reviewCount = lectureQueryRepository.findReviewCount(ids);
Map<Long, Long> bookmarkCount = lectureQueryRepository.findBookmarkCount(ids);
Map<Long, Double> reviewAverageScore = lectureQueryRepository.findReviewAverageScore(ids);
Map<Object, List<Review>> reviewsByLectureId = lectureQueryRepository.findAllReviewsByIds(ids)
.stream()
.collect(Collectors.groupingBy(review -> review.getLecture().getId()));

return lectures.getContent().stream()
.map(lecture -> {

List<String> tags = reviewsByLectureId.get(lecture.getId())
.stream()
.map(Review::getTags)
.toList();

List<TagGroup> tagGroups = getTagGroups(tags);

Double averageScore = reviewAverageScore.getOrDefault(lecture.getId(), 0.0);
Double roundedAverageScore = Math.round(averageScore * 2) / 2.0;

return LectureListReadResponse.LectureInfo.of(
lecture,
reviewCount.getOrDefault(lecture.getId(), 0L),
bookmarkCount.getOrDefault(lecture.getId(), 0L),
roundedAverageScore,
tagGroups,
lectureQueryRepository.findAllReviewsById(lecture.getId()));
})
.collect(Collectors.toList());
}

private LectureCategory findMainSubCategory(Integer mainCategoryId, Integer subCategoryId) {
return Arrays.stream(LectureCategory.values())
.filter(lectureCategory -> lectureCategory.getMainCategoryId().equals(mainCategoryId))
Expand Down
Loading

0 comments on commit f24783e

Please sign in to comment.