This document discusses how Eventbrite built a social network using MongoDB to power social recommendations on their site. It describes how user, event, and order data is stored in MongoDB collections to enable querying neighbors and recommended events. Challenges around the dynamic and flexible nature of the social graph and performance needs are also outlined. The system provides recommendations by fetching a user's neighbors, their events, and scoring each possible event.
8. Challenges
• Dynamic
• Neighbors change often
• Neighborsʼ events change often
• Flexibility
• Want to incorporate other social graphs
• Product may evolve quickly
• Performance
• We need really fast reads
• Frequent writes
8
Friday, December 3, 2010
9. Why MongoDB?
• Performance
• Flexible schema design
• Easy to work with
• We felt comfortable MongoDB would mature as
our needs became more demanding
9
Friday, December 3, 2010
10. Providing Recommendations
1. User visits http://eventbrite.com/mytickets/
2. Fetch neighbors
3. Fetch neighborsʼ events
4. Score each possible event
5. Return recommendations
10
Friday, December 3, 2010
11. MongoDB setup
• One non-sharded replica set
• Two DBs on Large EC2 instances
• One arbiter
• Three collections
• Users
• Events
• Orders
11
Friday, December 3, 2010
12. User Data in MongoDB
12
{ "_id": 4558992,
}
Unique User Id
Friday, December 3, 2010
13. User Data in MongoDB
13
{ "_id": 4558992,
"events" : {
"all_ids": [ 116706, 179487, 16389, 827496 ],
"curr_ids": [ 827496 ],
},
}
Past and current
attendance
Friday, December 3, 2010
19. Recommended Events Query
Two + n queries
1. Get neighbors
nns = db.users.find({_id : {$in : user.nn_ids}})
2. Get possible event recommendations:
db.events.find({_id : {$in : nns.events.all}})
n.For each event, get total attendee count
db.orders.find({_eid : event_id})
19
Friday, December 3, 2010
20. Recommended Events Query
Two + n queries
1. Get neighbors
nns = db.users.find({_id : {$in : user.nn_ids}})
2. Get possible event recommendations:
db.events.find({_id : {$in : nns.events.all}})
n.For each event, get total attendee count
db.orders.find({_eid : event_id})
20
Optimization opportunity:
Embed orders in Event records
Friday, December 3, 2010
21. Updating Neighbors
Two queries, one update
1. Get all orders for a userʼs past events:
uids = db.orders.find({_id : {$in : user.events.all}})
2. Get all neighbors:
nns = db.users.find({_id : {$in : uids}})
➡Score neighbors
3. Update nn_ids
db.users.update({_id : uid},
{$set : {nn_ids: nn}})
21
Friday, December 3, 2010
22. Facebook Friendʼs Events
Two queries
1. Get FB friends
db.users.find({fb._id : {$in : fb.friends}})
2. Get events FB friends are attending
db.events.find({_id : {$in : fb_friends_events}})
22
Friday, December 3, 2010
23. The Future
• Incorporate other social networks
• Iterate scoring algorithm
• Count recommendation impressions
23
Friday, December 3, 2010