-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
61 additions
and
0 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
recipes/4_higher_level_data_structures/implement_a_social_graph/meta.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
title: Implement a Simple Social Graph | ||
credit: | ||
- Michael Bleigh | ||
tags: | ||
- sets | ||
- abstractions |
30 changes: 30 additions & 0 deletions
30
recipes/4_higher_level_data_structures/implement_a_social_graph/recipe.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 %} |
24 changes: 24 additions & 0 deletions
24
recipes/4_higher_level_data_structures/implement_a_social_graph/social_graph.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |