코딩과 결혼합니다

230824 - 인기 순위 태그 조회하기 본문

코딩과 매일매일♥/Seoulvival

230824 - 인기 순위 태그 조회하기

코딩러버 2023. 8. 25. 18:47
728x90

관련글

https://coding-s2-chaewon.tistory.com/142

 

230810 - 태그를 누르면 해당 태그의 post가 조회되도록 하기

와이어 프레임 이전에 인기 순위 태그를 불러왔다면 이번에는 그 태그를 클릭하였을 때 해당하는 게시물을 '프론트가 원하는 개수만큼' 조회할 수 있게 할 것이다. 프론트에서 'limit : n' 과 같은

coding-s2-chaewon.tistory.com


와이어 프레임

#구, 동과 같은 경우는 프론트쪽에서 핸들링하는게 편하다 하셔서 백에서는 신경 쓰지 않음!!

 

오늘 내가 설명하고자 하는 기능은 바로 인기해시태그를 6위까지 만들어 프런트로 보내주는 것이다.

'현재 HOT한 해시태그' 

 

모든 카테고리의 내용들이 포함된 전체,  그리고 다른 3개의 카테고리가 있다.(후기, 동향소통, 생활정보)

전체를 누르면 전체에 대한 해시태그 인기순위가

카테고리를 누르면 카테고리별 해시태그 인기순위가 나올것이다.

그래서 나는 API를 두 개로 나누어 기능을 만들었다.


post 테이블의 컬럼들

    TagController
    
    //전체 태그 인기순위
    @GetMapping("/All")
    public List<String> allRankNumber(){
        return tagService.allRankNumber();
    }

    //카테고리별 태그 인기순위
    @GetMapping("/category")
    public List<String> categoryRankNumber(@RequestParam String category){
        return tagService.categoryRankNumber(category);
    }

전체는 입력값으로 아무것도 받지 않고, 카테고리는 Param 형식으로 category를 받는다.

 

TagService

    //전체 - 태그 순위
    public List<String> allRankNumber() {
        List<Post> postList = postRepository.findAll();
        List<String> rankedIds = getHashTagsFromPosts(postList);

        return getTopRankedTags(rankedIds, 6);
    }

    //카테고리 - 태그 순위
    public List<String> categoryRankNumber (String category) {
        List<Post> postList = postRepository.findAllBycategory(category);
        List<String> rankedIds = getHashTagsFromPosts(postList);

        return getTopRankedTags(rankedIds, 6);
    }
    
    
    //주어진 리스트에서 상위 N개의 요소를 선택하는 메서드
    private List<String> getTopRankedTags(List<String> rankedIds, int limit) {
        return rankedIds.stream().limit(limit).collect(Collectors.toList());
    }
    
     //postList에서 해시태그를 추출하고 인기순으로 정렬된 태그 목록을 반환
    private List<String> getHashTagsFromPosts(List<Post> postList) {
        Map<String, Integer> idFrequencyMap = new HashMap<>();

        for (Post post : postList) {
            if (Objects.isNull(post.getHashtag())) {
                continue;
            }

            String hashTag = post.getHashtag();
            String[] hashTagList = hashTag.split("#");
            for (String tagName : hashTagList) {
                if (!tagName.isEmpty()) {
                    idFrequencyMap.put(tagName, idFrequencyMap.getOrDefault(tagName, 0) + 1);
                }
            }
        }

        return idFrequencyMap.entrySet().stream()
                .sorted((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

전체나 카테고리나 거의 비슷하니 카테고리 쪽을 설명을 하자면

List<Post> postList = postRepository.findAllBycategory(category);
입력받아온 category와 같은 카테고리명을 가진 post들을 모두 가져와서 postList에 담는다.

List rankedIds = getHashTagsFromPosts(postList);
다음 postList를 하나씩 돌며 hashTag가 없는 post들은 그대로 넘겨버리고 있는 post들은 
#을 기준으로 split 한다. 그럼 하나의 문자열이었던 tag들이 여러개로 쪼개어 진다.
split을 하는 과정에서 ""(공백) 이 생기는데 공백이 아닌 것들만 가져와서 빈도수를 센다. 

.sorted((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()))
그리고 빈도수가 많은 것부터 내림차순으로 정렬해주었다.

return getTopRankedTags(rankedIds, 6);
limit으로 필요한 6개 까지만 놔두고 나머지는 잘라낸다.

포스트맨으로 확인한 결과


이번 프로젝트에서 사용하지 않을 기능이지만 오늘자 가장 많이 쓰인 카테고리도 간단하게 뽑아내 보겠다.

   TagController
   
   //오늘 검색 태그 인기순위
    @GetMapping("/today")
    public List <String> todayRankNumber(){
        return tagService.todayRankNumber();
    }
   TagService    

   //today 인기 태그 순위
    public List<String> todayRankNumber() {
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN); // 오늘의 시작 일시 (00:00:00)
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); // 오늘의 종료 일시 (23:59:59)

        List<Post> postList = postRepository.findByCreatedAtBetween(todayStart, todayEnd);

        List<String> rankedIds = getHashTagsFromPosts(postList);

        return getTopRankedTags(rankedIds, 10);
    }
PostRepository

List<Post> findByCreatedAtBetween(LocalDateTime todayStart, LocalDateTime todayEnd);

이렇게 하면 오늘자 post를 모두 뽑아낸 다음에 태그의 인기순위를 뽑을 수 있다.