How to get same rank for same scores in Redis' ZRANK?
If I have 5 members with scores as follows
a - 1 b - 2 c - 3 d - 3 e - 5
ZRANK of c returns 2, ZRANK of d returns 3 Is there a way to get same rank for same scores? Example: ZRANK c = 2, d = 2, e = 3 If yes, then how to implement that in spring-data-redis?
Any real solution needs to fit the requirements, which are kind of missing in the original question. My 1st answer had assumed a small dataset, but this approach does not scale as dense ranking is done (e.g. via Lua) in O(N) at least.
So, assuming that there are a lot of users with scores, the direction that for_stack suggested is better, in which multiple data structures are combined. I believe this is the gist of his last remark.
To store users' scores you can use a Hash. While conceptually you can use a single key to store a Hash of all users scores, in practice you'd want to hash the Hash so it will scale. To keep this example simple, I'll ignore Hash scaling.
This is how you'd add (update) a user's score in Lua:
local hscores_key = KEYS local user = ARGV local increment = ARGV local new_score = redis.call('HINCRBY', hscores_key, user, increment)
Next, we want to track the current count of users per discrete score value so we keep another hash for that:
local old_score = new_score - increment local hcounts_key = KEYS local old_count = redis.call('HINCRBY', hcounts_key, old_score, -1) local new_count = redis.call('HINCRBY', hcounts_key, new_score, 1)
Now, the last thing we need to maintain is the per score rank, with a sorted set. Every new score is added as a member in the zset, and scores that have no more users are removed:
local zdranks_key = KEYS if new_count == 1 then redis.call('ZADD', zdranks_key, new_score, new_score) end if old_count == 0 then redis.call('ZREM', zdranks_key, old_score) end
This 3-piece-script's complexity is O(logN) due to the use of the Sorted Set, but note that N is the number of discrete score values, not the users in the system. Getting a user's dense ranking is done via another, shorter and simpler script:
local hscores_key = KEYS local zdranks_key = KEYS local user = ARGV local score = redis.call('HGET', hscores_key, user) return redis.call('ZRANK', zdranks_key, score)
ZRANK – Redis, But I knew that the sorted set does not have same rank even thouth they have same score. My questiong is this. Can I get a same rank when the Redis ranks the members of a set from small to large by scores. The members of an ordered set are unique, but scores can be repeated. Collections are implemented through hash tables, so the complexity of adding, deleting and searching is O (1).
You can achieve the goal with two Sorted Set: one for member to score mapping, and one for score to rank mapping.
- Add items to member to score mapping:
ZADD mem_2_score 1 a 2 b 3 c 3 d 5 e
- Add the scores to score to rank mapping:
ZADD score_2_rank 1 1 2 2 3 3 5 5
- Get score first:
ZSCORE mem_2_score c, this should return the score, i.e.
- Get the rank for the score:
ZRANK score_2_rank 3, this should return the dense ranking, i.e.
In order to run it atomically, wrap the Add, and Search operations into 2 Lua scripts.
Issue 266 in redis: Sorted set has not a same rank even though it , Is there a way to get same rank for same scores? Example: ZRANK c = 2, d = 2, e = 3. If yes, then how to implement that in spring-data-redis For instance, when there are 5 items with scores: 1, 2, 2, 2, 3, I'd like to have those three central items to have the same rank (1), while the highest score gets rank 0 (with ZREVRANGE), and the lowest gets rank 4.
Then there's this Pull Request - https://github.com/antirez/redis/pull/2011 - which is dead, but appears to make dense rankings on the fly. The original issue/feature request (https://github.com/antirez/redis/issues/943) got some interest so perhaps it is worth reviving it /cc @antirez :)
Quick study on using Redis as a scoring engine · GitHub, Get the groups associated with the player in context. #. groups = -> redis hack since score doesn't mean rank, ie items with the same score do. # not have the I only need to be able to sort by score and get ranks by score. Using Redis' sorted sets a can easily store users' scores like so: ZADD leaderboard:gamemode1 100 user1 ZADD leaderboard:gamemode1 300 user2 however, I am struggelig to figure out, how to best store the percentage values belonging to the scores of 100 and 300.
The rank is unique in a sorted set, and elements with the same score are ordered (ranked) lexically.
There is no Redis command that does this "dense ranking"
You could, however, use a Lua script that fetches a range from a sorted set, and reduces it to your requested form. This could work on small data sets, but you'd have to devise something more complex for to scale.
How To Manage Sorted Sets in Redis, Note that if two members have the same score, the one that comes first alphabetically will have the lower rank. Like zscore , zrank and zrevrank The elements having the same score are returned in lexicographical order (this follows from a property of the sorted set implementation in Redis and does not involve further computation). The optional LIMIT argument can be used to only get a range of the matching elements (similar to SELECT LIMIT offset, count in SQL).
Use case: how to rank 2 millions users per score, in realtime (with , We had to find another solution. We choose Redis, which is an in-memory database, extremely fast and reliable. It's the 7th database the most used in the world Returns the rank of member in the sorted set stored at key, with the scores ordered from low to high. The rank (or index) is 0-based, which means that the member with the lowest score has rank 0. Use ZREVRANK to get the rank of an element with the scores ordered from high to low. *Return value.
Redis - Sorted Set Zrank Command, Redis ZRANK command returns the rank of member in the sorted set stored at the key, with the scores ordered from low to high. The rank (or index) is 0-based, Suppose you have data for students' names with their mathematics scores. Some students got same percentage so they would get the same rank. Your task is to rank them on the basis of their scores without breaking sequence. In the example shown below, highlighted ones are the students with their same scores.
How to Implement a Simple Redis Leaderboard, This will have the effect of updating the existing string with the new score. We will be using the ZADD command to update scores, ZRANK to get a player's rank, The difference is that each member of a sorted set is associated with a score, allowing them to be sorted from the smallest score to the largest. As with sets, every member of a sorted set must be unique, though multiple members can share the same score.