![Page 1: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/1.jpg)
2 App DesignsUsing MongoDB
![Page 2: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/2.jpg)
Kyle [email protected]
![Page 3: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/3.jpg)
@hwaet
![Page 4: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/4.jpg)
What we'll cover:Brief intro
Feed reader
Website analyitcs
Questions
![Page 5: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/5.jpg)
Intro
![Page 6: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/6.jpg)
MongoDBRich data model
Replication and automatic failover
Sharding
![Page 7: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/7.jpg)
Use casesSocial networking and geolocation
E-commerce
CMS
Analytics
Production deployments: http://is.gd/U0VkG6
![Page 8: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/8.jpg)
Demo
![Page 9: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/9.jpg)
Feed reader
![Page 10: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/10.jpg)
Four collectionsUsers
Feeds
Entries
Buckets
![Page 11: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/11.jpg)
Users{ _id: ObjectId("4e316f236ce9cca7ef17d59d"), username: 'kbanker', feeds: [ { _id: ObjectId("4e316f236ce9cca7ef17d54c"), name: "GigaOM" }, { _id: ObjectId("4e316f236ce9cca7ef17d54d"), name: "Salon.com" } { _id: ObjectId("4e316f236ce9cca7ef17d54e"), name: "Foo News" } ], latest: Date(2011, 7, 25)}
![Page 12: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/12.jpg)
Indexdb.users.ensureIndex( { username: 1 }, { unique: true } )
![Page 13: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/13.jpg)
Feeds{ _id: ObjectId("4e316b8a6ce9cca7ef17d54b"), url: 'http://news.foo.com/feed.xml/', name: 'Foo News', subscriber_count: 2, latest: Date(2011, 7, 25)}
Indexdb.feeds.ensureIndex( { url: 1 }, { unique: true
![Page 14: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/14.jpg)
Adding a feed subscription// Upsertdb.feeds.update( { url: 'http://news.foo.com/feed.xml/', name: 'Foo News'}, { $inc: {subscriber_count: 1} }, true )
![Page 15: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/15.jpg)
Adding a feed subscription// Add this feed to user feed listdb.users.update( {_id: ObjectId("4e316f236ce9cca7ef17d59d") }, { $addToSet: { feeds: { _id: ObjectId("4e316b8a6ce9cca7ef17d54b"), name: 'Foo News' } })
![Page 16: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/16.jpg)
Removing a feedsubscription
db.users.update( { _id: ObjectId("4e316f236ce9cca7ef17d59d") }, { $pull: { feeds: { _id: ObjectId("4e316b8a6ce9cca7ef17d54b"), name: 'Foo News' } } )
![Page 17: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/17.jpg)
Removing a feedsubscription
db.feeds.update( {url: 'http://news.foo.com/feed.xml/'}, { $inc: {subscriber_count: -1} } )
![Page 18: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/18.jpg)
Entries (populate inbackground)
{ _id: ObjectId("4e316b8a6ce9cca7ef17d54b"), feed_id: ObjectId("4e316b8a6ce9cca7ef17d54b"), title: 'Important person to resign', body: 'A person deemed very important has decided...', reads: 5, date: Date(2011, 7, 27)}
![Page 19: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/19.jpg)
What we need nowPopulate personal feeds (buckets)
Avoid lots of expensive queries
Record what's been read
![Page 20: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/20.jpg)
Without bucketing// Naive query runs every timedb.entries.find( feed_id: {$in: user_feed_ids}).sort({date: 1}).limit(25)
![Page 21: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/21.jpg)
With bucketing// A bit smarter: only runs onceentries = db.entries.find( { date: {$gt: user_latest }, feed_id: { $in: user_feed_ids } ).sort({date: 1})
![Page 22: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/22.jpg)
Indexdb.entries.ensureIndex( { date: 1, feed_id: 1} )
![Page 23: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/23.jpg)
bucket = { _id: ObjectId("4e3185c26ce9cca7ef17d552"), user_id: ObjectId("4e316f236ce9cca7ef17d59d"), date: Date( 2011, 7, 27 ) n: 100, entries: [ { _id: ObjectId("4e316b8a6ce9cca7ef17d5ac"), feed_id: ObjectId("4e316b8a6ce9cca7ef17d54b"), title: 'Important person to resign', body: 'A person deemed very important has decided...', date: Date(2011, 7, 27), read: false }, { _id: ObjectId("4e316b8a6ce9cca7ef17d5c8"), feed_id: ObjectId("4e316b8a6ce9cca7ef17d54b"), title: 'Panda bear waves hello', body: 'A panda bear at the local zoo...', date: Date(2011, 7, 27), read: false } ]}
![Page 24: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/24.jpg)
db.buckets.insert( buckets )db.users.update( { _id: ObjectId("4e316f236ce9cca7ef17d59d") } { $set: { latest: latest_entry_date } })
![Page 25: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/25.jpg)
Viewing a personal feed// Newestdb.buckets.find( { user_id: ObjectId("4e316f236ce9cca7ef17d59d") }).sort({date: -1}).limit(1)
![Page 26: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/26.jpg)
Viewing a personal feed// Next newest (that's how we paginate)db.buckets.find( { user_id: ObjectId("4e316f236ce9cca7ef17d59d"), date: { $lt: previous_reader_date } }).sort({date: -1}).limit(1)
![Page 27: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/27.jpg)
Indexdb.buckets.ensureIndex( { user_id: 1, date: -1 } )
![Page 28: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/28.jpg)
Marking a feed itemdb.buckets.update( { user_id: ObjectId("4e316f236ce9cca7ef17d59d"), 'entries.id': ObjectId("4e316b8a6ce9cca7ef17d5c8")}, { $set: { 'entries.$.read' : true })
![Page 29: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/29.jpg)
Marking a feed itemdb.entries.update( { _id: ObjectId("4e316b8a6ce9cca7ef17d5c8") }, { $inc: { read: 1 } })
![Page 30: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/30.jpg)
Sharding note:Buckets collection is eminently shardable
Shard key: { user_id: 1, date: 1 }
![Page 31: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/31.jpg)
Websiteanalyitcs
![Page 32: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/32.jpg)
Challenges:Real-time reporting.
Efficient use of space.�
Easily wipe unneeded data.
![Page 33: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/33.jpg)
TechniquesPre-aggregate the data.
Pre-construct document structure.
Store emphemeral data in a separatedatabase.
![Page 34: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/34.jpg)
Two collections:Each collection gets its own database.
Collections names are time-scoped.
Clean, fast removal of old data.
![Page 35: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/35.jpg)
// Collections holding totals for each day, stored// in a database per monthdays_2011_5days_2011_6days_2011_7...// Totals for each month...months_2011_1_4months_2011_5_8months_2011_9_12...
![Page 36: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/36.jpg)
Hours and minutes{ _id: { uri: BinData("0beec7b5ea3f0fdbc95d0dd47f35"), day: '2011-5-1' }, total: 2820, hrs: { 0: 500, 1: 700, 2: 450, 3: 343, // ... 4-23 go here } // Minutes are rolling. This gives real-time // numbers for the last hour. So when you increment // minute n, you need to $set minute n-1 to 0. mins: { 1: 12, 2: 10, 3: 5, 4: 34 // ... 5-60 go here }}
![Page 37: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/37.jpg)
Updating daydocument...
![Page 38: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/38.jpg)
// Update 'days' collection at 5:37 p.m. on 2011-5-1// Might want to queue increments so that $inc is greater// than 1 for each write...id = { uri: BinData("0beec7b5ea3f0fdbc95d0dd47f35"), day: '2011-5-1' };update = { $inc: { total: 1, 'hrs.17': 1, 'mins.37': 1 }, $set: { 'mins.36': 0} };// Update collection containing days 1-5db.days_2011_5.update( id, update );
![Page 39: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/39.jpg)
Months and days{ _id: { uri: BinData("0beec7b5ea3f0fdbc95d0dd47f35"), month: '2011-5' }, total: 34173, months: { 1: 4000, 2: 4300, 3: 4200, 4: 5000, 5: 5100, 6: 5700, 7: 5873 // ... 8-12 go here }}
![Page 40: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/40.jpg)
Updating monthdocument...
![Page 41: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/41.jpg)
// Update 'months' collection at 5:37 p.m. on 2011-5-1query = { uri: BinData("0beec7b5ea3f0fdbc95d0dd47f35"), month: '2011-5' };update = { $inc: { total: 1, 'months.5': 1 } };// Update collection containing days 1-5db.month_2011_1_4.update( query, update );
![Page 42: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/42.jpg)
ReportingMust provide data at multiple resolutions(second, minute, etc.).
We have the raw materials for that.
Application assembles the dataintelligently.
![Page 43: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/43.jpg)
Summary
![Page 44: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/44.jpg)
Feed ReaderRich documents
Incremental modifiers�
Bucketing strategy
![Page 45: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/45.jpg)
Website AnalyticsPre-aggregate data
Time-scoped databases and collections
![Page 48: Getting Started with MongoDB: 4 Application Designs](https://reader033.vdocuments.site/reader033/viewer/2022060108/55515baab4c9059f768b4b1b/html5/thumbnails/48.jpg)
Thank you