Practical MongoDB

43
Will Button - @wfbutton Practical MongoDB

description

Slide notes from Desert Code Camp 2014. This talk focuses on using the MEAN Stack to build an app that uses Facebook authentication for access, demonstrates advanced permissions for reading an authenticated user's Facebook data, and generating a data visualization using the D3.js library and custom Angular directives.

Transcript of Practical MongoDB

Page 1: Practical MongoDB

Will Button - @wfbutton

Practical MongoDB

Page 2: Practical MongoDB

From template to production

Many resources exist for individual components.Getting them to work together is a different story.

Page 3: Practical MongoDB

{name: ‘Will Button’,contact: [twitter: ‘@wfbutton’, email: ‘[email protected]’, web: ‘www.two4seven.me’],role: [‘dev’, ‘ops’, ‘it’],company: ‘myList.com’

}

Page 4: Practical MongoDB

mean stackfacebook

passport.jsd3.js

Page 5: Practical MongoDB

The problem.Participants competing in a challenge log meals, workouts and health data into a private Facebook group

Facebook newsfeed algorithmNo reportingDon’t want to lose demographics

Can we use existing frameworks to make it better without losing the parts that work well?

Page 6: Practical MongoDB

The solution.Tools and

TechnologiesPractical

Application

Page 7: Practical MongoDB
Page 8: Practical MongoDB

Step 1: MEAN Stack Template

git clone http://github.com/linnovate/mean.git

Page 9: Practical MongoDB

Connecting Facebook…

https://developers.facebook.com/apps

Page 10: Practical MongoDB

Configure passport

Page 11: Practical MongoDB

Facebook PermissionsDefault: profile, friends list, email

Can’t read newsfeed by default

Reading newsfeed requires valid accessToken

Page 12: Practical MongoDB

Facebook Permissions

https://developers.facebook.com/docs/facebook-login/permissions/

Page 13: Practical MongoDB

What about this accessToken thing?

> db.users.findOne({ provider: "facebook" }){

"__v" : 0,"_id" : ObjectId("52f6fc252ae38687577cc688"),"currentchallenge" : ObjectId("5308d9756d7d30a94b681b2d"),"email" : "[email protected]","facebook" : {

"username" : "will.button.56","updated_time" : "2014-01-06T22:33:03+0000","verified" : true,"locale" : "en_US","timezone" : -7,"email" : "[email protected]","gender" : "male","education" : [

{ "type" : "High School", "school" : { "name" : "Sidney High School", "id" : "110094965686846" } }],"favorite_athletes" : [

{ "name" : "CrossFit Endurance", "id" : "182015510972" },{ "name" : "Lucas Parker", "id" : "346667935460586" }

],"favorite_teams" : [

{ "name" : "Dallas Cowboys", "id" : "99559607813" }],"work" : [

{ "start_date" : "0000-00", "employer" : { "name" : "myList", "id" : "105017792957809" } },{ "end_date" : "0000-00", "start_date" : "2004-07-01", "employer" : { "name" : "NightHawk Radiology Services", "id" :

"115173631830635" } }],"bio" : "CrossFit Level 1 (CF-L1) Trainer","location" : { "name" : "Jost Van Dyke, British Virgin Islands", "id" : "327610993996350" },"hometown" : { "name" : "Sidney, Texas", "id" : "108011082555210" },"link" : "https://www.facebook.com/will.button.56","last_name" : "Button","first_name" : "Will","name" : "Will Button","id" : "100001902024344"

},"name" : "Will Button","provider" : "facebook","username" : "will.button.56"

}}

All of this for FREE$$$$

But no accessToken

Page 14: Practical MongoDB

Passport.js

Refreshes oauth accessToken on login

YIKES!

Functional, but not scalable.

Page 15: Practical MongoDB

User.js Model

Updated user.js model to store accessToken

Page 16: Practical MongoDB

Using Facebook OpenGraph

Page 17: Practical MongoDB

Displaying Entries

Page 18: Practical MongoDB
Page 19: Practical MongoDB
Page 20: Practical MongoDB

Stored Documents{

"user" : ObjectId("52f6fc252ae38687577cc688"),

"message" : "I ate my stuff","challenge" :

ObjectId("5302e4e445bae1611e2e60d9"),"_id" :

ObjectId("53125a106184fe00006e46d6"),"likes" : {

"data" : [ ]},"comments" : {

"data" : [ ]},"updated_time" : ISODate("2014-03-

01T22:07:12.442Z"),"created_time" : ISODate("2014-03-

01T22:07:12.442Z"),"__v" : 0

}

Page 21: Practical MongoDB

Journal Data Model

var JournalSchema = new Schema({created_time: {

type: Date,default: Date.now

},updated_time: {

type: Date,default: Date.now

},message: {

type: String},comments: {

data: [CommentSchema]},likes: {

data: [LikesSchema]},user: {

type: Schema.ObjectId,ref: 'User'

},challenge: {

type: Schema.ObjectId,ref: 'Challenge'

}});

var LikesSchema = new Schema({id: {

type: String},name: {

type: String}

});

Page 22: Practical MongoDB

Controller (part of it anyway)

Page 23: Practical MongoDB

All accessible via Routes

Page 24: Practical MongoDB

Recap: Where are we now?

Page 25: Practical MongoDB

Reporting

Page 26: Practical MongoDB

Aggregation Framework

Page 27: Practical MongoDB

Aggregation : Quick ReviewPipeline for multiple stages of document transformations for producing aggregated results

Name Description$project Reshapes a document stream. $project can rename, add, or remove fields as well as create computed values and sub-documents.$match Filters the document stream, and only allows matching documents to pass into the next pipeline stage. $match uses standard MongoDB queries.$limit Restricts the number of documents in an aggregation pipeline.$skip Skips over a specified number of documents from the pipeline and returns the rest.$unwind Takes an array of documents and returns them as a stream of documents.$group Groups documents together for the purpose of calculating aggregate values based on a collection of documents.$sort Takes all input documents and returns them in a stream of sorted documents.$geoNear Returns an ordered stream of documents based on proximity to a geospatial point.

Page 28: Practical MongoDB

db.journals.aggregate( { $group: { _id: "$from.name", numposts: { $sum: 1 } } }, { $project: { who: "$from.name", numposts: 1 } }, { $sort: {_id: 1 } } )

{"result" : [

{"_id" : "Andrew","numposts" : 83

},{

"_id" : "Ben","numposts" : 108

},########### results truncated for brevity ##########

{"_id" : "Tara","numposts" : 20

},{

"_id" : "Will","numposts" : 26

}],"ok" : 1

}

Page 29: Practical MongoDB

Accessible via:

http://localhost:3000/journals/ppu

Page 30: Practical MongoDB

Page is rendered By a

controller

With a directive

Using D3 injected as a

service

Page 31: Practical MongoDB

The Controllerangular.module('mean.reports').controller('ReportsController', ['$scope', '$http', function($scope, $http){ $http({ method: 'GET', url: '/journals/ppu' }).then(function(data, status) { $scope.d3Data = data.data; });}]);

Page 32: Practical MongoDB

d3Bars Directive

this

thisgets normalized to

Page 33: Practical MongoDB

d3Bars Directive

D3 library injected as a service

Page 34: Practical MongoDB

The d3 service is accessible because we add the service to our

footer

And inject it as a dependency

Page 35: Practical MongoDB

The service itself simply downloads d3.js

Page 36: Practical MongoDB

Directives are just reusable pieces of code

Restrict where the directive can be used

A/E/C

Scope refers to the type of isolated scope:= two way data binding with the parent DOM object@ one way data binding with the parent DOM object

& expression binding with the parent DOM object

Page 37: Practical MongoDB

link is basically a controller

variables either specified on declaration or use

defaults

Page 38: Practical MongoDB
Page 39: Practical MongoDB

Where do we go from here?

Page 40: Practical MongoDB

Where do we go from here?

Add new aggregation queries to journals controller

Build new reports/d3 visualizations in

directives.js

Add directives to any page:<d3-bars data="d3Data”></d3-bars>

Page 41: Practical MongoDB

The mistakes people I make.

Request the right Facebook

permissions

Setup your Facebook

Developers Account

Make your Facebook app public (at least for a few

minutes)

Facebook Graph Explorer

Hardcode dummy data first.

Don’t assume .success(),

wait for it .then()

Page 42: Practical MongoDB

Do this now:

• Clone the MEAN stack• Stub out dummy data• Build a d3 graph• Stick around

Page 43: Practical MongoDB

www.two4seven.me/dcc@wfbutton