티스토리 뷰

프로젝트를 진행하는 중 검색한 지역을 기준으로 인기 지역 TOP5의 랭킹을 구현해야했다. 

지역을 검색할 때 마다 데이터가 계속 업데이트되고 , Redis의 Sorted Set을 이용하면 랭킹을 쉽게 구현할 수 있을거 같아 Redis를 이용해 인기 지역 TOP5 랭킹을 구현했다.

하지만 Redis는 특성 상 같은 점수를 중복처리를 하지않고, value값으로 다시 정렬하기에 동점데이터가 있을때, 따로 처리를 해줘야한다.

 

내가 동점처리한 방법은 Map 자료구조를 이용해 score값을 기준으로 다시 검색데이터를 분류해 같은 score값을 가진 데이터를 카운트 해준뒤, reverseRange()를 이용해 동점처리 된 데이터도 공동순위에 들어가게 구현하였다.

 

지역을 검색할때마다 해당 검색어(지역)을 value에 저장하고, score에 1을 주면서 검색량을 올려주었다.

public void ranking(String content){
    ZSetOperations<String,String> stringStringZSetOperations = redisTemplate.opsForZSet();

    double score = 0.0;

    try{
    // 검색을하면 해당검색어(content)를 value에 저장하고, score에 1을 주어 score를 올려준다.
        redisTemplate.opsForZSet().incrementScore("ranking",content,1);
    }
    catch(Exception e){
        System.out.println(e.getMessage());
    }
    
}

 

Map<Double,Integer> score에 score값을 기준으로 다시 검색데이터를 분류해준다.

score.put(test_score,score.getOrDefault(test_score, 0)+1); 로 같은 score값을 가질때 +1을 해 카운트해준다.

public List<Map.Entry<String, Integer>> rank_list(){
    ZSetOperations<String,String> stringStringZSetOperations = redisTemplate.opsForZSet();
    Long redis_size = redisTemplate.opsForZSet().size("ranking");
    Double test_score =null;
    Map<Double,Integer> score = new HashMap<>(); //스코어를 담기위한 Map

    for(int i = 0; i < redis_size; i++) {
        Set<String> test = stringStringZSetOperations.reverseRange("ranking", i, i);
        for(String str : test) {
            test_score = stringStringZSetOperations.score("ranking", str);
            score.put(test_score,score.getOrDefault(test_score, 0)+1);
		
        }
    }
    // score = {8.0=1, 2.0=3, 1.0=10, 5.0=1, 3.0=2}

 

score가 top5안에 들어가고 가중치(score)을 가진 value값이 공동(2개이상 존재할때)일때, same_score라는 변수에 같은 가중치를 가진 value의 수 -1을 해 same_score에 증가시켜준다.

-1을 해준 이유는 ranking을 구할때 0부터 4+same_score 순위까지 구현하기 때문에 공동 순위로 들어가는 value값들중 하나는 top5안에 들어가기 때문이다.

예를 들어 같은 가중치를 가진 value가 4개일때, same_score에 3을 증가시켜준다.

 

ZsetOperations의 reverseRange()를 이용해 0순위부터 4+same_score순위로 구현해 TOP5에 공동순위까지 구현하였다.

List<Map.Entry<Double, Integer>> sortedList = new ArrayList<>(score.entrySet());
// key인 double값을 기준으로 내림차순 정렬
sortedList.sort(Collections.reverseOrder(Map.Entry.comparingByKey()));

int same_score=0;
//score가 top5 안에 들어가고 ,같은 score를 가진 데이터가 2개이상일때
for (int i = 0; i <= 4 && i < sortedList.size(); i++) {
    Map.Entry<Double, Integer> entry = sortedList.get(i);
    if(entry.getValue()>1) {
        same_score += entry.getValue() - 1;
        System.out.println("Score: " + entry.getKey() + ", Value: " + entry.getValue());
    }
}

// 공동 순위 처리한 top5 랭킹
Set<String> scoreRange = stringStringZSetOperations.reverseRange("ranking",0,4+same_score);

 

TOP5를 점수기준으로 내림차순 정렬하기 위해 comparator를 이용해  value 값을 기준으로 정렬을 했다.

List<Integer> scoreRange_score = new ArrayList<>();

for(String str : scoreRange) {
    int i;
    double d = stringStringZSetOperations.score("ranking", str);
    i = Integer.parseInt(String.valueOf(Math.round(d))); //double값 int로 변환
    scoreRange_score.add(i);
}

List<String> targetList = new ArrayList<>(scoreRange);
Map<String, Integer> rank = new HashMap<>();
for(int j=0;j<scoreRange.size();j++){
    rank.put(targetList.get(j),scoreRange_score.get(j));
}

List<Map.Entry<String, Integer>> entryList = new LinkedList<>(rank.entrySet());
entryList.sort(new Comparator<Map.Entry<String, Integer>>() {
    @Override
    public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
        return o2.getValue() - o1.getValue();
    }
});

// entryList = [논현동=8, 상계동=5, 길동=3, 방학동=3, 창동=2, 신림동=2, 쌍문동=2, 수유동=1,
// 석촌동=1, 공릉동=1, 번동=1, 삼성동=1, 노량진동=1, 독산동=1, 대치동=1, 고덕동=1, 둔촌동=1]

return entryList;

 

Reference

https://sabarada.tistory.com/105

https://yuricoding.tistory.com/m/151

https://velog.io/@cgw0519/Java-HashMap-Value-%EA%B8%B0%EC%A4%80%EC%9C%BC%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0

'JAVA' 카테고리의 다른 글

ElasticSearch와 연동후 인덱스 설정하기  (0) 2023.08.07
Garbage Collection  (0) 2023.04.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함