Skip to content

Instantly share code, notes, and snippets.

@clemens
Created July 3, 2012 16:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clemens/3040762 to your computer and use it in GitHub Desktop.
Save clemens/3040762 to your computer and use it in GitHub Desktop.
Redis sorted set ranking changes
redis.zadd('scores:20120701', 10, 'alice')
redis.zadd('scores:20120701', 7, 'bob')
redis.zadd('scores:20120701', 5, 'carol')
# resulting ranking:
# 1 - alice
# 2 - carol
# 3 - bob
redis.zadd('scores:20120702', 7, 'alice')
redis.zadd('scores:20120702', 9, 'bob')
redis.zadd('scores:20120702', 15, 'carol')
# resulting ranking:
# 1 - carol
# 2 - bob
# 3 - alice
redis.zsomething('scores:changes:20120701-20120702', 'scores:20120701', 'scores:20120702')
# expected result:
# carol: +2
# bob: 0
# alice: -2
old_ranks = redis.zrevrangebyscore('scores:20120701', '+inf', '-inf')
new_ranks = redis.zrevrangebyscore('scores:20120702', '+inf', '-inf')
redis.multi do |redis|
old_ranks.each_with_index do |user, i|
redis.zadd('scores:ranking:20120701', i + 1, user)
end
new_ranks.each_with_index do |user, i|
redis.zadd('scores:ranking:20120702', i + 1, user)
end
end
redis.zinterstore('scores:changes:20120701-20120702', ['scores:ranking:20120701', 'scores:ranking:20120702'], :weights => [1, -1])
@clemens
Copy link
Author

clemens commented Jul 3, 2012

Use case: I want to show a ranking of users including a little icon that indicates how their ranking has changed compared to rankings of previous days/weeks/periods (up arrow = better ranking etc.). Is there a way to do this directly in Redis? I imagine I could store away the rankings two separate sorted sets and do a weighted zunionstore over those sets but I'd much prefer a direct approach. :)

@clemens
Copy link
Author

clemens commented Jul 3, 2012

I've added a simple iterative solution based on intersecting the two rankings and weighing the newer ranking as negative. It's simple and I guess it scales OK since it's a one-off calculation but I'm still curious if there's a better way. :)

@adrienbaron
Copy link

Having the same problem, will probably use your solution ;). Unless you figured out something better since 2012 ^^?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment