Browse files

Add social graph recipe.

  • Loading branch information...
1 parent 1713916 commit 94258e7288ff6f5290d1121505db7015ad4c7f8d Michael Bleigh committed with tlossen Apr 12, 2010
View
7 recipes/4_higher_level_data_structures/implement_a_social_graph/meta.yml
@@ -0,0 +1,7 @@
+---
+title: Implement a Simple Social Graph
+credit:
+ - Michael Bleigh
+tags:
+ - sets
+ - abstractions
View
30 recipes/4_higher_level_data_structures/implement_a_social_graph/recipe.md
@@ -0,0 +1,30 @@
+### Problem
+
+You want to use Redis to implement a social graph for users in some kind of application, with one and two directional relationships available (following and friendship).
+
+### Solution
+
+Use the built-in set functionality of Redis to construct `follow`, `follower`, and `blocked` lists keyed to each user's unique ID. In raw redis it looks something like this:
+
+ redis> SADD user:1:follows 2
+ (integer) 1
+ redis> SADD user:2:followers 1
+ (integer) 1
+ redis> SADD user:3:follows 1
+ (integer) 1
+ redis> SADD user:1:followers 3
+ (integer) 1
+ redis> SADD user:1:follows 3
+ (integer) 1
+ redis> SADD user:3:followers 1
+ (integer) 1
+ redis> SINTER user:1:follows user:1:followers
+ 1. 3
+
+### Discussion
+
+Redis comes with the ability to construct "sets", which are collections of unique values assigned to a key. By creating both a "follows" and "followers" list for a given user, we are able to quickly and easily pull that information as well as calculate their "friendships" using a simple set intersection.
+
+Implementing such a system in Ruby looks something like this:
+
+{% code_snippet social_graph.rb %}
View
24 recipes/4_higher_level_data_structures/implement_a_social_graph/social_graph.rb
@@ -0,0 +1,24 @@
+REDIS = Redis.new
+
+class User
+ def self.find(*ids)
+ # gets a set of User objects given IDs
+ end
+
+ def follow(other_user)
+ REDIS.sadd("user:#{self.id}:follows", other_user.id)
+ REDIS.sadd("user:#{other_user.id}:followers", self.id)
+ end
+
+ def followers
+ User.find(*REDIS.smembers("user:#{self.id}:followers"))
+ end
+
+ def follows
+ User.find(*REDIS.smembers("user:#{self.id}:follows"))
+ end
+
+ def friends
+ User.find(*REDIS.sinter("user:#{self.id}:followers", "user:#{self.id}:follows"))
+ end
+end

0 comments on commit 94258e7

Please sign in to comment.