Transcript

MongoDB + Node.js

Building first app with MongoDB and Node.js

3

Agenda

MongoDB + Node.js

Driver

ODM's

MEAN Stack

Meteor

4

Ola, I'm Norberto!

Norberto Leite

Technical Evangelist

Madrid, Spain

@nleite

[email protected]

http://www.mongodb.com/norberto

MongoDB Node.js

INFACT

MongoDB JavaScript

8

Few reasons why

Flexible AgileWeb

Language

9

MongoDB + Javascript

• MongoDB Shell

– JS interperter

• MongoDB MapReduce

– Runs on top of V8

– Map and Reduce functions are JS functions

• Native support for Node.js

– One of the most used Drivers out there!

– https://www.npmjs.com/package/mongodb

Node.js

11

2 Foundations

Events Streams

12

2 Foundations

• Events / Event Loop

– Single Thread Applications

– No threads

– Events Emitter

– Event Queue

– Known Events

• Streams

– Read, Write, Both

– Unix Pipes

– We use it extensively!

Install

npm package

$ npm install mongodb

Compatibility

http://docs.mongodb.org/ecosystem/drivers/node-js/#compatibility

16

Compatibility w/ MongoDB

Initialize Project

package.json file

$ mkdir firstappnodejs

$ cd firstappnodejs

$ npm init

package.json file

$ mkdir firstappnodejs

$ cd firstappnodejs

$ npm init

...{

"name": "firstappnodejs",

"version": "0.0.1",

"description": "Small demo webinar application",

"main": "index.js",

"scripts": {

"test": "workitout"

},

"repository": {

"type": "git",

"url": "git://github.com/nleite/firstappnodejs"

},

"dependencies": {

"mongodb": "~2.0"

},

"keywords": [http://docs.mongodb.org/ecosystem/drivers/node-js/#compatibility

"demo",

"nodejs",

"mongodb"

],

"author": "Norberto Leite",

"license": "Apache 2.0",

"bugs": {

"url": "https://github.com/nleite/firstappnodejs/issues"

},

"homepage": "https://github.com/nleite/firstappnodejs"

}

package.json file

$ mkdir firstappnodejs

$ cd firstappnodejs

$ npm init

...{

"name": "firstappnodejs",

"version": "0.0.1",

"description": "Small demo webinar application",

"main": "index.js",

"scripts": {

"test": "workitout"

},

"repository": {

"type": "git",

"url": "git://github.com/nleite/firstappnodejs"

},

"dependencies": {

"mongodb": "~2.0"

},

"keywords": [

"demo",

"nodejs",

"mongodb"

],

"author": "Norberto Leite",

"license": "Apache 2.0",

"bugs": {

"url": "https://github.com/nleite/firstappnodejs/issues"

},

"homepage": "https://github.com/nleite/firstappnodejs"

}

Install our new firstappnodejs app!

$ npm install

> [email protected] install …

> [email protected] install

> [email protected] node_modules/mongodb

├── [email protected] ([email protected], [email protected],

[email protected], [email protected])

└── [email protected] ([email protected], [email protected])

firstappnodejs/ $ ls

node_modules package.json

Connect

boot up MongoDB Server

$ mkdir ~/firstappdb

$ mongod --dbpath ~/firstappdb

boot up MongoDB Server

$ mkdir ~/firstappdb

$ mongod --dbpath ~/firstappdb --auth

--keyfile ~/n.pem

https://www.mongodb.com/products/mongodb-enterprise-advanced

boot up MongoDB Server

$ mkdir ~/firstappdb

$ mongod --dbpath ~/firstappdb --auth

--keyfile ~/n.pem

https://www.mongodb.com/products/mongodb-enterprise-advanced

var MongoClient = require('mongodb').MongoClient,

assert = require('assert');

Connect

var MongoClient = require('mongodb').MongoClient,

assert = require('assert');

//connection uri

var uri = "mongodb://localhost:27017/firstapp"

Connect

var MongoClient = require('mongodb').MongoClient,

assert = require('assert');

//connection uri

var uri = "mongodb://localhost:27017/firstapp"

//connect to MongoDB

MongoClient.connect(uri, function(err, db){

assert.equal(null, err);

console.log("Connected correctly to server");

db.close();

});

Connect

29

Connection Pooling

• No traditional Pooling mechanism

– Single thread process

• Sockets to pipeline operations

• Failover

– Buffering up operations

– bufferMaxEntries

– numberOfRetries

– retryMiliSeconds

http://mongodb.github.io/node-mongodb-native/2.0/api/Db.html

CRUD

var insertDocuments = function(db, cb){

//we don't need to explicitly create a collection

var collection = db.collection('myCollection');

collection.insertMany([

{"mongodb": "is just awesome"},

{"nodejs": "so awesome"}

], function(err, result){

assert.equal(null, err);

//inserted 2 documents

assert.equal(2, result.insertedCount);

//invoke callback

cb(result);

});

}

Insert

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

var insertDocuments = function(db, cb){

//we don't need to explicitly create a collection

var collection = db.collection('myCollection');

collection.insertMany([

{"mongodb": "is just awesome"},

{"nodejs": "so awesome"}

], function(err, result){

assert.equal(null, err);

//inserted 2 documents

assert.equal(2, result.insertedCount);

//invoke callback

cb(result);

});

}

Insert

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

var insertDocuments = function(db, cb){

//we don't need to explicitly create a collection

var collection = db.collection('myCollection');

collection.insertMany([

{"mongodb": "is just awesome"},

{"nodejs": "so awesome"}

], function(err, result){

assert.equal(null, err);

//inserted 2 documents

assert.equal(2, result.insertedCount);

//invoke callback

cb(result);

});

}

Insert

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

var insertDocuments = function(db, cb){

//we don't need to explicitly create a collection

var collection = db.collection('myCollection');

collection.insertMany([

{"mongodb": "is just awesome"},

{"nodejs": "so awesome"}

], function(err, result){

assert.equal(null, err);

//inserted 2 documents

assert.equal(2, result.insertedCount);

//invoke callback

cb(result);

});

}

Insert

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

MongoClient.connect(uri, function(err, db) {

assert.equal(null, err);

console.log("Sweet! Talking to Server");

insertDocuments(db, function() {

db.close();

});

});

Insert

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

MongoClient.connect(uri, function(err, db) {

assert.equal(null, err);

console.log("Sweet! Talking to Server");

insertDocuments(db, function() {

db.close();

});

});

Insert

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert

var updateDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.updateOne( {"mongodb": "is just awesome"},

{$set: {"users": ["nleite"]}}, function( err, result){

assert.equal(null, err);

assert.equal(1, result.modifiedCount);

console.log("Cool, just updated");

cb(result);

});

}

Update

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#update

var updateDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.updateOne( {"mongodb": "is just awesome"},

{$set: {"users": ["nleite"]}}, function( err, result){

assert.equal(null, err);

assert.equal(1, result.modifiedCount);

console.log("Cool, just updated");

cb(result);

});

}

Update

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#update

var updateDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.updateOne( {"mongodb": "is just awesome"},

{$set: {"users": ["nleite"]}}, function( err, result){

assert.equal(null, err);

assert.equal(1, result.modifiedCount);

console.log("Cool, just updated");

cb(result);

});

}

Update

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#update

var updateDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.updateOne( {"mongodb": "is just awesome"},

{$set: {"users": ["nleite"]}}, function( err, result){

assert.equal(null, err);

assert.equal(1, result.modifiedCount);

console.log("Cool, just updated");

cb(result);

});

}

Update

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#update

MongoClient.connect(uri, function(err, db) {

assert.equal(null, err);

console.log("Ok, I can now update!");

updateDocuments(db, function() {

db.close();

});

});

Update

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#update

Remove

var removeDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.deleteOne( {"users": "nleite"},

function( err, result){

assert.equal(null, err);

assert.equal(1, result.deletedCount);

console.log("purged the @nleite contaminateddata!");

cb(result);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#remove

Remove

var removeDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.deleteOne( {"users": "nleite"},

function( err, result){

assert.equal(null, err);

assert.equal(1, result.deletedCount);

console.log("purged the @nleite contaminateddata!");

cb(result);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#remove

Remove

var removeDocument = function(db, cb){

var collection = db.collection("myCollection");

collection.deleteOne( {"users": "nleite"},

function( err, result){

assert.equal(null, err);

assert.equal(1, result.deletedCount);

console.log("purged the @nleite contaminateddata!");

cb(result);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#remove

Remove

MongoClient.connect(uri, function(err, db) {

assert.equal(null, err);

console.log("Ok, I can now delete!");

removeDocuments(db, function() {

db.close();

});

});

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#remove

Find

var findAllDocuments = function(db, cb){

var collection = db.collection('myDocuments');

//or collection.find()

collection.find({}).toArray(function(err, docs){

assert.equal(err, null);

assert.equal(1, docs.length);

console.log("Gotcha! found "+ docs.length);

console.dir(docs);

cb(docs);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#find

Find

var findAllDocuments = function(db, cb){

var collection = db.collection('myDocuments');

//or collection.find()

collection.find({}).toArray(function(err, docs){

assert.equal(err, null);

assert.equal(1, docs.length);

console.log("Gotcha! found "+ docs.length);

console.dir(docs);

cb(docs);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#find

Find

var findAllDocuments = function(db, cb){

var collection = db.collection('myDocuments');

//or collection.find()

collection.find({}).toArray(function(err, docs){

assert.equal(err, null);

assert.equal(1, docs.length);

console.log("Gotcha! found "+ docs.length);

console.dir(docs);

cb(docs);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#find

Flexibility

Schema Flexibility

Different Schemas

var insertDifferentShapes = function(db, cb){

var doc1 = {"name": "Norberto", "talks": [

{"nodejs":10}, {"java":15}, "python":11]};

var doc2 = {"name": "Bryan", "webinars": 30};

var coll = db.collection("content")

coll.insertMany( [doc1, doc2], function(err, result){

assert.equal(err, null);

assert.equal(2, result.insertedCount);

console.log("Sweet, inserted "+ result.insertedCount);

cb(result);

});

}

http://docs.mongodb.org/manual/data-modeling/

Different Schemas

var insertDifferentShapes = function(db, cb){

var doc1 = {"name": "Norberto", "talks": [

{"nodejs":10}, {"java":15}, "python":11]};

var doc2 = {"name": "Bryan", "webinars": 30};

var coll = db.collection("content")

coll.insertMany( [doc1, doc2], function(err, result){

assert.equal(err, null);

assert.equal(2, result.insertedCount);

console.log("Sweet, inserted "+ result.insertedCount);

cb(result);

});

}

http://docs.mongodb.org/manual/data-modeling/

WriteConcerns

WriteConcern w:1

WriteConcern w:2

WriteConcern j:true

Different WriteConcerns

var insertSuperImportant = function(db, cb){

var customer = {"name": "Manny Delgado", "age": 14};

var coll = db.collection("customers");

var writeConcern = {"w": "majority"};

col.insertOne( customer, writeConcern, function(err, result){

assert.equal(err, null);

assert.equal(1, result.insertedCount);

console.log("Inserted super important record");

cb(result);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/WriteConcernError.html

Different WriteConcerns

var insertSuperImportant = function(db, cb){

var customer = {"name": "Manny Delgado", "age": 14};

var coll = db.collection("customers");

var writeConcern = {"w": "majority"};

col.insertOne( customer, writeConcern, function(err, result){

assert.equal(err, null);

assert.equal(1, result.insertedCount);

console.log("Inserted super important record");

cb(result);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/WriteConcernError.html

Read Preference

60

Read Preference

• Read from Primary (default)

ReadPreference.PRIMARY

• Read from Primary Preferably

ReadPreference.PRIMARY_PREFERRED

• Read from Secondary

ReadPreference.SECONDARY

• Read from Secondary Preferably

ReadPreference.SECONDARY_PREFERRED

• Read from Nearest Node

ReadPreference.NEAREST

http://mongodb.github.io/node-mongodb-native/2.0/api/ReadPreference.html

Read From Nearest

var readNearestWaterMelonColor = function(db, cb){

var rp = ReadPreference.NEAREST;

var coll = db.collection("products", {ReadPreference:rp});

var query = {"color": "water melon green"};

collection.find(query).toArray(function(err, docs){

assert.equal(err, null);

assert.equal(1, docs.length);

console.log("So many products: "+ docs.length);

console.dir(docs);

cb(docs);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/ReadPreference.html

Read From Nearest

var readNearestWaterMelonColor = function(db, cb){

var rp = ReadPreference.NEAREST;

var coll = db.collection("products", {ReadPreference:rp});

var query = {"color": "water melon green"};

collection.find(query).toArray(function(err, docs){

assert.equal(err, null);

assert.equal(1, docs.length);

console.log("So many products: "+ docs.length);

console.dir(docs);

cb(docs);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/ReadPreference.html

Read From Nearest

var readNearestWaterMelonColor = function(db, cb){

var rp = ReadPreference.NEAREST;

var coll = db.collection("products", {readPreference:rp});

var query = {"color": "water melon green"};

collection.find(query).toArray(function(err, docs){

assert.equal(err, null);

assert.equal(1, docs.length);

console.log("So many products: "+ docs.length);

console.dir(docs);

cb(docs);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/ReadPreference.html

Aggregation

Aggregation

var aggregateAvgAgeGender = function( db, cb){

//{age:XX, name:"user name", gender: "M/F"}

var pipeline = [

{$group: { "_id": "$gender", avg_age: {$avg: "$age"}}},

];

var coll = db.collection("users");

var cursor = coll.aggregate(pipeline);

cursor.forEach( function(x){

console.log("Gender " + x._id + " age average " + x.avg_age)

}, function(x) {

cb(cursor);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#aggregate

Aggregation

var aggregateAvgAgeGender = function( db, cb){

//{age:XX, name:"user name", gender: "M/F"}

var pipeline = [

{$group: { "_id": "$gender", avg_age: {$avg: "$age"}}},

];

var coll = db.collection("users");

var cursor = coll.aggregate(pipeline);

cursor.forEach( function(x){

console.log("Gender " + x._id + " age average " + x.avg_age)

}, function(x) {

cb(cursor);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#aggregate

Aggregation

var aggregateAvgAgeGender = function( db, cb){

//{age:XX, name:"user name", gender: "M/F"}

var pipeline = [

{$group: { "_id": "$gender", avg_age: {$avg: "$age"}}},

];

var coll = db.collection("users");

var cursor = coll.aggregate(pipeline);

cursor.forEach( function(x){

console.log("Gender " + x._id + " age average " + x.avg_age)

}, function(x) {

cb(cursor);

});

}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#aggregate

Aggregation

var aggregateAvgAgeGender = function( db, cb){

//{age:XX, name:"user name", gender: "M/F"}

var pipeline = [

{$match:{"age": $gt: 18}},

{$group: { "_id": "$gender", avg_age: {$avg: "$age"}}},

{$project:{"ID": "$_id", "average": "$avg_age" }}

];

var cursor = coll.aggregate(pipeline);

var coll = db.collection("users");

cursor.forEach( function(x){

console.log("Gender " + x._id + " age average " + x.avg_age)

}, function(x) {

cb(cursor);

});}

http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#aggregate

ODM's

Mongoose

71

Mongoose

• Schema Validation

• Casting

• Business Logic Wrapper

• http://mongoosejs.com/

Simple Mongoose

var mongoose = require('mongoose'), assert =require('assert')

var Schema = mongoose.Schema;

//define a schema

var userSchema = new Schema({ name: String, age:Number})

//create static members

userSchema.statics.findByName = function( name, cb){

return this.find( {"name": name}, cb);

}

Simple Mongoose

//generate a model

var User = mongoose.model('User', userSchema);

//initiate the new user, validates the given arguments

var u1 = User({name:"Many Delgado", age:14});

//just save it

u1.save(function(err){

assert.equal(null, err);

});

74

Other Projects

Project Repository

MongoSkin https://github.com/kissjs/node-mongoskin

Mongolia https://github.com/masylum/mongolia

Mongojs https://github.com/mafintosh/mongojs

MongoSmash https://github.com/bengl/mongosmash

MEAN Stack

76

MEAN Stack

• MongoDB

• Express.js

• Angular JS

• Node.js

Express is a minimal and flexible Node.js web

application framework that provides a robust

set of features for web and mobile

applications.

AngularJS lets you extend HTML vocabulary

for your application. The resulting

environment is extraordinarily expressive,

readable, and quick to develop

Building your first app with MongoDB: Creating

a REST API using the MEAN Stack

https://www.mongodb.com/blog/post/building-

your-first-application-mongodb-creating-rest-

api-using-mean-stack-part-1

Meteor

Meteor is a complete open source platform

for building web and mobile apps in pure

JavaScript.

82

Meteor

• Responsiveness

• Reactiveness

• Multiplatform

• Unified Package System

• Hot Deploys

https://www.meteor.com/try

METEOR: Build IOS and Android Apps

that are a delight to use

http://www.mongodb.com/blog/post/meteor-

build-ios-and-android-apps-are-delight-use

Recap

85

What we talked about today…

• Node.js is a very productive language

– Our driver is highly adopted

– Updated

– Fully compatible

• CRUD Operations

– Insert, Update, Remove, Delete

• Write Concerns

– Flexible to write

• Read Preferences

– Flexible to read

• Aggregation Framework

– Analytics at your fingertips

86

Large Ecosystem

• Mongoose

• Mean Stack

• Meteor

• Many other projects

87

Where to next?

• Questions on the driver:

– https://groups.google.com/forum/#!forum/node-mongodb-native

• Issues:

– https://jira.mongodb.org/browse/NODE/?selectedTab=com.atlass

ian.jira.jira-projects-plugin:summary-panel

• Tutorial:

– http://mongodb.github.io/node-mongodb-native/2.0/

• Todays code:

– https://github.com/nleite/firstappnodejs

• Other:

– http://www.mongodb.com/norberto

http://www.mongodb.com/webinar/managing-

mission-critical-app-downtime

89

For More Information

Resource Location

Case Studies mongodb.com/customers

Presentations mongodb.com/presentations

Free Online Training education.mongodb.com

Webinars and Events mongodb.com/events

Documentation docs.mongodb.org

MongoDB Downloads mongodb.com/download

Additional Info [email protected]

Blog blog.mongodb.com

90

Register now: mongodbworld.com

Use Code NorbertoLeite for additional 25% Off*Come as a group of 3 or more – Save another 25%

http://cl.jroo.me/z3/v/D/C/e/a.baa-Too-many-bicycles-on-the-van.jpg

Questions?

@nleite

[email protected]

http://www.mongodb.com/norberto