life is egg
핫이슈 게시물 좋아요기준 top3 본문
상황
1. 마감기한 때문에 JPA 쿼리메서드로만 구현
2. 레디스, 쿼리dsl 적용X
3. 좋아요기준으로 만들어야하는데 좋아요엔티티와 게시글엔티티 연관관계 설정X
4. 좋아요 테이블은 postId 와 userId로만 구성
일단 구현먼 저 하고 나중에 개선하자는 생각으로 만들었다
첫번째 문제는
오늘 작성한 게시물을 가져오는건데
처음에
List<T_exercise> findIdByCreatedDateString(String dateTime);
여기서 파라미터은 dateTime은
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd"))
이렇게해서 현재 시간 기준으로 작성된 일자가 겹치면 조회해서 가져오는 식으로 작성 할 계획이였는데

Timestamped의 createdDate 의 타입이 이미 LocalDateTime 으로 고정되어있어서 고민이였다..
String 타입인 .. datedTime이 조회가 안되었는데 .. 여기서 내가 createdDate를 String 타입으로 변경해서 사용하면
이미 다른곳에서 쓰고있는것도 분명 영향을 줄거같아서
String 타입의 생성일자를 표시해주는 컬럼을 하나 추가해서 당일 게시물 조회하는 방식으로 처리해줬다
이건 추후 레디스를 이용한다면 하루동안 캐시에 저장되는 좋아요 수로 개선할 수 있을 듯 하다.!!
따라서 ..

스트링 타입으로 컬럼을 하나 추가시켜줘서 이제 timestamped 를 상속받으면 게시물이나 무언가 생성될때 생성일자,수정일자,생성일자(string) 이렇게 3개의 컬럼이 생긴다
일단 이렇게 처리해줘서
오늘생성된 게시물을 찾아서 list로 불러오는 방식을 택했다
두번째 문제는
이제 여기서 해당하는 postid에 달린 좋아요 수를 가져오면되는데
나는 좋아요수를 기록하는 컬럼이 없고 좋아요 레포 조회시 해당하는 postId로 등록된 유저id의 컬럼수를 세는 방식으로 초반에 설계 했기 때문에... 여기서도 문제가 생겼다.
아.. 이것도 좋아요 성능개선해서 ..레디스좀 이용해보고싶다,...
일단 목표를 구현먼저로 잡았으니 비효율 적이더라도 만들어내야한다..
그래서 처음엔 쿼리메소드를 Map 형태로 만들어서 key 값에는 오늘 올라온 게시글에 해당하는 postid
value 값에는 grouby같은걸로 postid를 묶어서 좋아요 누른 userid의 갯수를 넣어줘서 해주고싶었는데..
지식이 짧아서 그런가 ... 도저히 쿼리메소드로 만들 수 가 없었다..
그래서 일단 list로 가져오고 Map형태로 구현해보자고 해서 만든게...
@Override
public List<T_exerciseBoardResponseDTO> getTop3PostByLike() {
List<T_exercise> exercises = t_exerciseRepository.findIdByCreatedDateString(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")));
List<T_exerciseBoardResponseDTO> top3Post = new ArrayList<>();
HashMap<T_exercise,Long> postSortByLike = new HashMap();
ValueComparator bvc = new ValueComparator(postSortByLike);
TreeMap<T_exercise,Long> sorted_map = new TreeMap<>(bvc);
for (T_exercise exercise : exercises) {
Long boardId = exercise.returnPostId();
Long countLike = tExerciseLikeService.countLike(boardId);
postSortByLike.put(exercise,countLike);
}
sorted_map.putAll(postSortByLike);
int count =0;
for (Map.Entry<T_exercise, Long> tExerciseLongEntry : sorted_map.entrySet()) {
T_exercise exercise = tExerciseLongEntry.getKey();
Long boardId = exercise.returnPostId();
Long countLike = tExerciseLongEntry.getValue();
String title = exercise.getTitle();
String content = exercise.getContent();
String imageUrl = exercise.getImageUrl();
LocalDateTime modifiedDate = exercise.getModifiedDate();
String username = exercise.getUser().getUsername();
String nickName = userService.getUserNickname(exercise.getUser());
T_exerciseBoardResponseDTO dto = new T_exerciseBoardResponseDTO(countLike, boardId, title, content, imageUrl, modifiedDate, username, nickName);
top3Post.add(dto);
count++;
if (count==3){
break;
}
}
return top3Post;
}
HashMap<T_exercise,Long> postSortByLike = new HashMap();
for (T_exercise exercise : exercises) {
Long boardId = exercise.returnPostId();
Long countLike = tExerciseLikeService.countLike(boardId);
postSortByLike.put(exercise,countLike);
}
일단 요거 두개는 ... Map을 구현 못한자의 최후이다...
key값에 게시물객체 value 값에 좋아요 갯수가 들어간다
이제 남은건.. value 값을 기준으로 내림차순 정리해서 3개까지만 가져와서 반환하고 싶은 내용만 반환하는것..
이거 완전 쿼리DSL 쓰고싶다는 생각이든다..
무튼 일단 내림차순으로 정리해야하니까
ValueComparator bvc = new ValueComparator(postSortByLike);
TreeMap<T_exercise,Long> sorted_map = new TreeMap<>(bvc);
sorted_map.putAll(postSortByLike);
그래서 일단 ...value 값기준으로 내림차순으로 만들어준다...
private class ValueComparator implements Comparator<T_exercise> {
Map<T_exercise, Long> base;
public ValueComparator(Map<T_exercise, Long> base) {
this.base = base;
}
// Note: this comparator imposes orderings that are inconsistent with equals.
public int compare(T_exercise a, T_exercise b) {
if (base.get(a) >= base.get(b)) { //반대로 하면 오름차순 <=
return -1;
} else {
return 1;
} // returning 0 would merge keys
}
}
내림차순으로 만들어주기...메소드 ..사실 이거 말고 찾은게 하나더 있는데 그건 value값기준 오름차순으로만 해주는 방법이라 내림차순 오름차순 둘다 가능한 방식으로 적용했다..
int count =0;
for (Map.Entry<T_exercise, Long> tExerciseLongEntry : sorted_map.entrySet()) {
T_exercise exercise = tExerciseLongEntry.getKey();
Long boardId = exercise.returnPostId();
Long countLike = tExerciseLongEntry.getValue();
String title = exercise.getTitle();
String content = exercise.getContent();
String imageUrl = exercise.getImageUrl();
LocalDateTime modifiedDate = exercise.getModifiedDate();
String username = exercise.getUser().getUsername();
String nickName = userService.getUserNickname(exercise.getUser());
T_exerciseBoardResponseDTO dto = new T_exerciseBoardResponseDTO(countLike, boardId, title, content, imageUrl, modifiedDate, username, nickName);
top3Post.add(dto);
count++;
if (count==3){
break;
}
}
그다음.. 3개까지만 받아와서 break; 필요한 정보만 줄려고... 꺼내서 준다 이거다... 눈물이 나온다... 하드코딩
쿼리DSL 해야겠지?
개선점이 매우 많아보인다...
n+1문제 나는지 확인해보기
groupby 생각해보기
패치조인 및 JPQL ~쿼리DSL 공부해서 적용시키기
추후에
레디스이용해서 좋아요 방식을 대폭 개선하기..
-> 이러면 좋아요 갯수를 저장해버리자 ..!
'개인공부 > 삽질' 카테고리의 다른 글
| presignedURL 적용 (0) | 2023.03.17 |
|---|---|
| 이메일 비동기처리 (0) | 2023.03.17 |
| org.h2.jdbc.JdbcSQLInvalidAuthorizationSpecException: Wrong user name or password (0) | 2023.01.11 |
| @Bean 등록 에러 (0) | 2023.01.11 |
| 게시글 삭제 시 댓글 삭제 (2) | 2022.12.29 |