SlideShare a Scribd company logo
Getting Started With MongoDB and
Node.JS
Jay Runkel
Principal Solutions Architect
jay.runkel@mongodb.com
@jayrunkel
2
3
GridFS
Driver
GridFS API
doc.jpg
(meta
data)
doc.jpg
(1)doc.jpg
(1)doc.jpg
(1)
fs.files fs.chunks
doc.jpg
4
5
Perl? What is this 1985?
6
Goal Today
• Help you get started with MongoDB and Node.JS
• Assumption:
– New to both technologies
– Programming Experience
– Database Experience
• Learn from my newbie confusion
7
Agenda
1. Why Node.JS and MongoDB?
2. Find and Insert
3. Node.JS async, event queue, flow control
4. Controlling multiple threads
– Bulk insert
MongoDB and Node.JS?
9
Marriage Made in Heaven
10
JavaScript and “JSON” throughout
Browser
JavaScript
Node.JS
JavaScriptJSON
BSON (JSON)
BSON
JSON
11
Documents are Rich Data Structures
{
first_name: ‘Paul’,
surname: ‘Miller’,
cell: ‘+447557505611’
city: ‘London’,
location: [45.123,47.232],
Profession: [banking, finance, trader],
cars: [
{ model: ‘Bentley’,
year: 1973,
value: 100000, … },
{ model: ‘Rolls Royce’,
year: 1965,
value: 330000, … }
]
}
Fields can contain an array of sub-documents
Fields
Typed field values
Fields can contain arrays
Do More With Your Data
MongoDB
{
first_name: ‘Paul’,
surname: ‘Miller’,
city: ‘London’,
location: [45.123,47.232],
cars: [
{ model: ‘Bentley’,
year: 1973,
value: 100000, … },
{ model: ‘Rolls Royce’,
year: 1965,
value: 330000, … }
}
}
Rich Queries
Find Paul’s cars
Find everybody in London with a car
built between 1970 and 1980
Geospatial
Find all of the car owners within 5km
of Trafalgar Sq.
Text Search
Find all the cars described as having
leather seats
Aggregation
Calculate the average value of Paul’s
car collection
Map Reduce
What is the ownership pattern of
colors by geography over time?
(is purple trending up in China?)
13
Aircraft Sensor
RTL-SDR
14
Sample Data
{
"_id" : "20160101000000:UA7549",
"icao" : "UA7549",
"callsign" : "UA7549",
"ts" : ISODate("2016-01-01T05:00:00Z"),
"events" : {
"a" : 1773,
"b" : 258,
"p" : [50,-60],
"s" : 345,
"t" : ISODate("2016-01-01T05:00:00Z"),
"v" : 299
}
}
15
Example: Find Query
• Find a flight status entry for United Airlines Flight 1234
– db.data.findOne({"callsign" : "UA7549"})
• Find a aircraft flying at less than 5000 feet
– db.data.findOne({"events.a" : {$lt : 5000}})
• Set value of note field
– db.data.update({"callsign" : "OY1949"},
{$set : {"note" : "spoke with captain"}})
Retrieve One Document in Node.JS
The Simple Things Don’t Always Seem Easy
17
The synchronous way
var MongoClient = require('mongodb').MongoClient;
var db = MongoClient.connect('mongodb://localhost:27017/adsb');
var col = db.collection('data');
var doc = col.findOne({"callsign" : "UA7549"});
console.log("Here is my doc: %j", doc);
db.close();
18
The synchronous way
var MongoClient = require('mongodb').MongoClient;
var db = MongoClient.connect('mongodb://localhost:27017/adsb');
var col = db.collection('data');
var doc = col.findOne({"callsign" : "UA7549"});
console.log("Here is my doc: %j", doc);
db.close();
19
It works this way in the mongoshell???
var col = db.getCollection("data");
var doc = col.findOne({"callsign" : "HR9368"});
printjson(doc);
Synchronous vs. Asychronous
Event Loop
21
Synchronous Programming
time
Func1 Func1 IO Func1 Func2 Func2 IO Func2
22
Asynchronous Programming
time
Func1
Func1 IO
Func1Func2
Func2 IO
Func2
IO Processing runs on separate
threads in parallel with main
processing thread
23
Callbacks
col.findOne({"callsign" : "UA7549"}, function (err, doc) {
assert.equal(null, err);
console.log("Here is my doc: %j", doc);
console.log(”All done!”);
• Execute findOne
• When it is done, call the callback function
• Callback function takes two arguments
– err – contains the error message or null
– doc – the result of the findOne call
• “All Done” will be printed before the “Here is my doc…”
24
Event queue
From: http://www.slideshare.net/takingblue/talk-nodejs-andisomorphicjavascript
25
Event queue
From: http://www.slideshare.net/takingblue/talk-nodejs-andisomorphicjavascript
MongoDB
26
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
Call Stack Driver API
Callback
Queue
Event Loop
27
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
Call Stack Driver API
Callback
Queue
Event Loop
find1234()
28
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
Call Stack Driver API
Callback
Queue
Event Loop
find1234()
col.findOne()
col.findOne()
29
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
Call Stack Driver API
Callback
Queue
Event Loop
col.updateMany()
col.findOne()
col.updateMany()
30
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
Call Stack Driver API
Callback
Queue
Event Loop
col.insert()
col.insert()
col.updateMany()
fo1_cb
31
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
Call Stack Driver API
Callback
Queue
Event Loop
console.log()
col.updateMany()
fo1_cb ins1_cb
32
Event Queue/Call Stack
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
function fo1_cb () {…}
Call Stack Driver API
Callback
Queue
Event Loop
fo1_cb()
col.updateMany()
ins1_cb
33
Event Queue/Call Stack
Call Stack Driver API
Callback
Queue
Event Loop
ins1_cb()
up1_cb
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
function ins1_cb () {…}
34
Event Queue/Call Stack
Call Stack Driver API
Callback
Queue
Event Loop
up1_cb()
function find1234 () {
col.findOne({_id: 1234},
fo1_cb);
find1234();
col.updateMany({color: “blue”},
{$set : {w : 5}}, up1_cb);
col.insert({product: 1234,
cost: 99}, ins1_cb);
console.log(“done”);
function up1_cb () {…}
Back to the findOne example
36
MongoDB Asynchronous Queries
var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
col.findOne({"callsign" : "UA7549"}, function (err, doc) {
assert.equal(null, err);
console.log("Here is my doc: %j", doc);
db.close();
});
});
37
Asynchronously
var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
col.findOne({"callsign" : "UA7549"}, function (err, doc) {
assert.equal(null, err);
console.log("Here is my doc: %j", doc);
db.close();
});
});
callback
38
Asynchronously
var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
col.findOne({"callsign" : "UA7549"}, function (err, doc) {
assert.equal(null, err);
console.log("Here is my doc: %j", doc);
db.close();
});
});
callback
39
This gets ugly fast
var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
var db = MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
col.findOne({"callsign" : "UA7549"}, function (err, doc) {
assert.equal(null, err);
console.log("Here is my doc: %j", doc);
col.updateOne({"callsign" : "UA7549"}, {$set : {"note" : "Spoke with the
pilot"}}, {}, function(err, result) {
assert.equal(null, err);
console.log("Note updated");
db.close();
});
});
});
40
Nested callbacks - yuck
async1(function(input, result1) {
async2(function(result2) {
async3(function(result3) {
async4(function(result4) {
async5(function(output) {
// do something with output
});
});
});
});
})
41
Solutions
• Break up into modules
• Use a Flow Control library
– async
– Step
• Promises
42
With Flow Control - Step
Step (
function connectToMongoDB (err, db) {
MongoClient.connect('mongodb://
localhost:27017/adsb', this);
},
function findOneDoc(err, db) {
if (err) console.log("Connect: %j",
err);
database = db;
collection = db.collection('data');
collection.findOne(csQuery, {}, this);
},
function updateDoc(err, doc) {
if (err) console.log("Find One: %j",
err);
console.log("Here is my doc: %j", doc);
collection.updateOne(csQuery,
{$inc : {"timesViewed" : 1}},{},this);
},
function findOneDoc2 (err, result) {
if (err)
console.log("Update error: %j", err);
collection.findOne(csQuery, {},
this);
},
function closeConnection(err, doc) {
if (err)
console.log("FindOne Doc: %j", err);
console.log("Note updated: %j",
doc);
database.close();
}
);
43
With Flow Control
Step (
function connectToMongoDB (err, db) {
MongoClient.connect('mongodb://
localhost:27017/adsb', this);
},
function findOneDoc(err, db) {
if (err) console.log("Connect: %j",
err);
database = db;
collection = db.collection('data');
collection.findOne(csQuery, {}, this);
},
function updateDoc(err, doc) {
if (err) console.log("Find One: %j",
err);
console.log("Here is my doc: %j", doc);
collection.updateOne(csQuery,
{$inc : {"timesViewed" : 1}},{},this);
},
function findOneDoc2 (err, result) {
if (err)
console.log("Update error: %j", err);
collection.findOne(csQuery, {},
this);
},
function closeConnection(err, doc) {
if (err)
console.log("FindOne Doc: %j", err);
console.log("Note updated: %j",
doc);
database.close();
}
44
With Flow Control
Step (
function connectToMongoDB (err, db) {
MongoClient.connect('mongodb://
localhost:27017/adsb', this);
},
function findOneDoc(err, db) {
if (err) console.log("Connect: %j",
err);
database = db;
collection = db.collection('data');
collection.findOne(csQuery, {}, this);
},
function updateDoc(err, doc) {
if (err) console.log("Find One: %j",
err);
console.log("Here is my doc: %j", doc);
collection.updateOne(csQuery,
{$inc : {"timesViewed" : 1}},{},this);
},
function findOneDoc2 (err, result) {
if (err)
console.log("Update error: %j", err);
collection.findOne(csQuery, {},
this);
},
function closeConnection(err, doc) {
if (err)
console.log("FindOne Doc: %j", err);
console.log("Note updated: %j",
doc);
database.close();
}
45
You can also execute in parallel
Step (
function connectToMongoDB (err, db) {
MongoClient.connect('mongodb://localhost:27017/adsb', this);
},
function executeParallel (err, db) {
if (err) console.log("Connect: %j", err);
var collection = db.collection('data');
database = db;
collection.findOne(csQuery, {}, this.parallel());
collection.updateOne(csQuery, {$inc : {"timesViewed" : 1}}, {}, this.parallel());
collection.findOne(csQuery, {}, this.parallel());
},
function closeConnection(err, doc1, upResult, doc2) {
if (err) console.log("Error: %j", err);
console.log("Here is doc1: %j", doc1);
console.log("Incremented: %j", upResult);
console.log("Here is doc2: %j", doc2);
database.close();
}
);
How do you deal with multiple find results?
47
Find Many - Cursor
• This works in the MongoShell
var col = db.getCollection("data");
var cursor = col.find({"events.a" : {$gt : 5000}});
while (cursor.hasNext()) {
printjson(cursor.next());
}
48
Find Many - Cursor
• This works in the MongoShell
var col = db.getCollection("data");
var cursor = col.find({"events.a" : {$gt : 5000}});
while (cursor.hasNext()) {
printjson(cursor.next());
}
• It does not work in Node.JS
• The MongoDB driver retrieves documents in batches from MongoDB
– Retrieving a new batch is asynchronous
49
Find Many - Streams
MongoClient.connect("mongodb://localhost:27017/adsb", function (err, db) {
var col = db.collection('data')
var stream = col.find({"events.a" : {$gt : 5000}}).stream();
stream.on('data', function(doc) {
console.log("Doc: %j", doc);
});
stream.on('error', function (doc) {
console.log("Query failed: %j", doc);
});
stream.on('end', function() {
console.log("All data retrieved.");
db.close();
});
});
50
Find Many - Streams
MongoClient.connect("mongodb://localhost:27017/adsb", function (err, db) {
var col = db.collection('data')
var stream = col.find({"events.a" : {$gt : 5000}}).stream();
stream.on('data', function(doc) {
console.log("Doc: %j", doc);
});
stream.on('error', function (doc) {
console.log("Query failed: %j", doc);
});
stream.on('end', function() {
console.log("All data retrieved.");
db.close();
});
});
‘data’ callback invoked
for each document
51
What about insert?
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
col.insert({x: 1, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Insert Complete");
db.close();
});
});
52
What if I have to insert 100M documents?
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
for (i = 1; i <= 100000000; i++) {
col.insert({x: i, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Insert Complete");
});
}
});
Let’s insert all 100,000,000
in parallel!!!!
53
What if I have to insert 100M documents?
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
for (i = 1; i <= 100000000; i++) {
col.insert({x: i, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Insert Complete");
db.close();
});
}
});
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
54
Event Queue/Call Stack
for (i = 1; i <= 100000000; i++) {
col.insert({x: i, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Insert C…");
});
}
Call Stack Driver API
Callback
Queue
Event Loop
55
Event Queue/Call Stack
for (i = 1; i <= 100000000; i++) {
col.insert({x: i, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Insert C…");
db.close();
});
Call Stack Driver API
Callback
Queue
Event Loop
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
56
Event Queue/Call Stack
for (i = 1; i <= 100000000; i++) {
col.insert({x: i, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Insert C…");
db.close();
});
Call Stack Driver API
Callback
Queue
Event Loop
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
col.insert()
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
57
Let’s try 5 at a time
var DOCS_TO_INSERT = 1000;
var numInsertsRunning = 0; // number of insert threads
var insertCount = 0; // number of documents inserted so far
MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) {
assert.equal(null, err);
var col = db.collection('data');
for (i = 0; i < 5; i++) {
++numInsertsRunning;
insertDocument(db, col, ++insertCount, i, function (err, result) {
console.log("All ", DOCS_TO_INSERT, " documents inserted.");
db.close();
});
}
});
58
insertDocument function
function insertDocument (db, col, docNum, threadNum, callback) {
col.insert({x: ++insertCount, y: 2, z: 3},
{},
function (err, result) {
assert.equal(null, err);
console.log("Thread: ", threadNum, " inserted doc: ", docNum, ".");
if (insertCount < DOCS_TO_INSERT)
insertDocument(db, col, ++insertCount, threadNum, callback);
else if (numInsertsRunning == 1) {
numInsertsRunning--;
callback(null, true);
}
else
numInsertsRunning--;
});
}
59
InsertDocument Callback Logic
col.insert({x: ++insertCount, y: 2, z: 3}, function (err, result) {
}
Have all the documents
been inserted?
Call insertDocument
again
Are other inserts still
running?
Do nothing & decrement
running thread count
All inserts done
Call the original callback
Yes Yes
No No
60
Bulk Inserts
• The previous example was for illustrative purposes
• MongoDB provides a buik write API that provides better performance for bulk writes
• The bulk write API batches up writes
– Batch writes with a single acknowledgement
• Use collection.bulkWrite
• Improve performance using multiple bulkWrite threads
– Previous example will be identical
– Replace collection.insert with collection.bulkWrite
61
Another word of caution
• All my examples established a MongoDB connection and then closed it
– This was for illustrative purposes
• Don’t continuously open and close MongoDB connections.
• Open a connection once once
– Use that connection through the life of the program
– Close it at the end
62
Summary
• Asynchronous vs synchronous programming
• Call stack, event loop, driver API
• Flow control
• Find, insert, update examples
• Managing multiple parallel threads
– bulk insert example
• Learn from my mistakes and misconceptions
Questions?
jay.runkel@mongodb.com
@jayrunkel
Github: https://github.com/jayrunkel/nodeJSWebJun2016

More Related Content

PPTX
Back to Basics Webinar 5: Introduction to the Aggregation Framework
PPTX
Webinar: Building Your First App in Node.js
PPTX
Back to Basics, webinar 2: La tua prima applicazione MongoDB
PDF
Indexing
PDF
MongoDB Performance Tuning
PPTX
MongoDB - Aggregation Pipeline
PPTX
Beyond the Basics 2: Aggregation Framework
PPTX
Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework
Back to Basics Webinar 5: Introduction to the Aggregation Framework
Webinar: Building Your First App in Node.js
Back to Basics, webinar 2: La tua prima applicazione MongoDB
Indexing
MongoDB Performance Tuning
MongoDB - Aggregation Pipeline
Beyond the Basics 2: Aggregation Framework
Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework

What's hot (20)

PPTX
MongoDB + Java - Everything you need to know
PPTX
MongoDB Aggregation
PDF
Java development with MongoDB
PDF
MongoDB Europe 2016 - Debugging MongoDB Performance
PDF
Hadoop - MongoDB Webinar June 2014
PDF
Inside MongoDB: the Internals of an Open-Source Database
PPTX
Webinar: Index Tuning and Evaluation
PPTX
Joins and Other Aggregation Enhancements Coming in MongoDB 3.2
PDF
Webinar: Building Your First App with MongoDB and Java
PDF
MongoDB World 2016: Deciphering .explain() Output
PPTX
Back to Basics: My First MongoDB Application
PPTX
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
PDF
MongoDB .local Toronto 2019: Using Change Streams to Keep Up with Your Data
PDF
MongoDB Performance Tuning
PPTX
Mythbusting: Understanding How We Measure the Performance of MongoDB
PDF
MongoDB Aggregation Framework
PPTX
Indexing Strategies to Help You Scale
PPTX
2014 bigdatacamp asya_kamsky
PDF
Aggregation Framework MongoDB Days Munich
PPT
Introduction to MongoDB
MongoDB + Java - Everything you need to know
MongoDB Aggregation
Java development with MongoDB
MongoDB Europe 2016 - Debugging MongoDB Performance
Hadoop - MongoDB Webinar June 2014
Inside MongoDB: the Internals of an Open-Source Database
Webinar: Index Tuning and Evaluation
Joins and Other Aggregation Enhancements Coming in MongoDB 3.2
Webinar: Building Your First App with MongoDB and Java
MongoDB World 2016: Deciphering .explain() Output
Back to Basics: My First MongoDB Application
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
MongoDB .local Toronto 2019: Using Change Streams to Keep Up with Your Data
MongoDB Performance Tuning
Mythbusting: Understanding How We Measure the Performance of MongoDB
MongoDB Aggregation Framework
Indexing Strategies to Help You Scale
2014 bigdatacamp asya_kamsky
Aggregation Framework MongoDB Days Munich
Introduction to MongoDB
Ad

Viewers also liked (18)

PPTX
Back to Basics Webinar 3: Schema Design Thinking in Documents
PPTX
Back to Basics, webinar 1: Introduzione a NoSQL
PPT
MongoDB gridfs
PPTX
MongoDB Internals
PPTX
MongoDB Operations for Developers
PPTX
PPTX
Get expertise with mongo db
KEY
Gridfs and MongoDB
PDF
MongoDB- Crud Operation
PPTX
MongoDB on EC2 and EBS
PPTX
An Enterprise Architect's View of MongoDB
PPTX
Introduction to MongoDB
PDF
Introduction to column oriented databases
PPTX
Back to Basics Webinar 6: Production Deployment
PPTX
Webinar: Back to Basics: Thinking in Documents
PDF
Mongo DB
PPT
Introduction to MongoDB
PDF
Grid FS
Back to Basics Webinar 3: Schema Design Thinking in Documents
Back to Basics, webinar 1: Introduzione a NoSQL
MongoDB gridfs
MongoDB Internals
MongoDB Operations for Developers
Get expertise with mongo db
Gridfs and MongoDB
MongoDB- Crud Operation
MongoDB on EC2 and EBS
An Enterprise Architect's View of MongoDB
Introduction to MongoDB
Introduction to column oriented databases
Back to Basics Webinar 6: Production Deployment
Webinar: Back to Basics: Thinking in Documents
Mongo DB
Introduction to MongoDB
Grid FS
Ad

Similar to Getting Started with MongoDB and NodeJS (20)

PDF
Latinoware
ODP
Mongo db dla administratora
PPTX
Data Management 3: Bulletproof Data Management
PDF
NoSQL meets Microservices
PDF
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
PDF
NoSQL meets Microservices - Michael Hackstein
ZIP
Javascript Everywhere From Nose To Tail
PDF
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
PDF
MongoDB dla administratora
PDF
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
PDF
Future of Web Apps: Google Gears
PPTX
Functional Programming In JS
PDF
HTML5 for the Silverlight Guy
PDF
What do you mean, Backwards Compatibility?
PPTX
Fact, Fiction, and FP
PDF
Herding types with Scala macros
PDF
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
PDF
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
PDF
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
PDF
Refactoring to Macros with Clojure
Latinoware
Mongo db dla administratora
Data Management 3: Bulletproof Data Management
NoSQL meets Microservices
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
NoSQL meets Microservices - Michael Hackstein
Javascript Everywhere From Nose To Tail
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
MongoDB dla administratora
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Future of Web Apps: Google Gears
Functional Programming In JS
HTML5 for the Silverlight Guy
What do you mean, Backwards Compatibility?
Fact, Fiction, and FP
Herding types with Scala macros
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Refactoring to Macros with Clojure

More from MongoDB (20)

PDF
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
PDF
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
PDF
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
PDF
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
PDF
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
PDF
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
PDF
MongoDB SoCal 2020: MongoDB Atlas Jump Start
PDF
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
PDF
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
PDF
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
PDF
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
PDF
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
PDF
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
PDF
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
PDF
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
PDF
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
PDF
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
PDF
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
PDF
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
PDF
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: MongoDB Atlas Jump Start
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...

Recently uploaded (20)

PDF
NewMind AI Monthly Chronicles - July 2025
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Big Data Technologies - Introduction.pptx
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
GamePlan Trading System Review: Professional Trader's Honest Take
PPTX
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
PDF
Machine learning based COVID-19 study performance prediction
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Electronic commerce courselecture one. Pdf
PPT
Teaching material agriculture food technology
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
[발표본] 너의 과제는 클라우드에 있어_KTDS_김동현_20250524.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
solutions_manual_-_materials___processing_in_manufacturing__demargo_.pdf
NewMind AI Monthly Chronicles - July 2025
MYSQL Presentation for SQL database connectivity
Diabetes mellitus diagnosis method based random forest with bat algorithm
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Big Data Technologies - Introduction.pptx
Understanding_Digital_Forensics_Presentation.pptx
NewMind AI Weekly Chronicles - August'25 Week I
GamePlan Trading System Review: Professional Trader's Honest Take
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
Machine learning based COVID-19 study performance prediction
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Advanced methodologies resolving dimensionality complications for autism neur...
Electronic commerce courselecture one. Pdf
Teaching material agriculture food technology
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
[발표본] 너의 과제는 클라우드에 있어_KTDS_김동현_20250524.pdf
Spectral efficient network and resource selection model in 5G networks
Dropbox Q2 2025 Financial Results & Investor Presentation
solutions_manual_-_materials___processing_in_manufacturing__demargo_.pdf

Getting Started with MongoDB and NodeJS

  • 1. Getting Started With MongoDB and Node.JS Jay Runkel Principal Solutions Architect [email protected] @jayrunkel
  • 2. 2
  • 4. 4
  • 5. 5 Perl? What is this 1985?
  • 6. 6 Goal Today • Help you get started with MongoDB and Node.JS • Assumption: – New to both technologies – Programming Experience – Database Experience • Learn from my newbie confusion
  • 7. 7 Agenda 1. Why Node.JS and MongoDB? 2. Find and Insert 3. Node.JS async, event queue, flow control 4. Controlling multiple threads – Bulk insert
  • 10. 10 JavaScript and “JSON” throughout Browser JavaScript Node.JS JavaScriptJSON BSON (JSON) BSON JSON
  • 11. 11 Documents are Rich Data Structures { first_name: ‘Paul’, surname: ‘Miller’, cell: ‘+447557505611’ city: ‘London’, location: [45.123,47.232], Profession: [banking, finance, trader], cars: [ { model: ‘Bentley’, year: 1973, value: 100000, … }, { model: ‘Rolls Royce’, year: 1965, value: 330000, … } ] } Fields can contain an array of sub-documents Fields Typed field values Fields can contain arrays
  • 12. Do More With Your Data MongoDB { first_name: ‘Paul’, surname: ‘Miller’, city: ‘London’, location: [45.123,47.232], cars: [ { model: ‘Bentley’, year: 1973, value: 100000, … }, { model: ‘Rolls Royce’, year: 1965, value: 330000, … } } } Rich Queries Find Paul’s cars Find everybody in London with a car built between 1970 and 1980 Geospatial Find all of the car owners within 5km of Trafalgar Sq. Text Search Find all the cars described as having leather seats Aggregation Calculate the average value of Paul’s car collection Map Reduce What is the ownership pattern of colors by geography over time? (is purple trending up in China?)
  • 14. 14 Sample Data { "_id" : "20160101000000:UA7549", "icao" : "UA7549", "callsign" : "UA7549", "ts" : ISODate("2016-01-01T05:00:00Z"), "events" : { "a" : 1773, "b" : 258, "p" : [50,-60], "s" : 345, "t" : ISODate("2016-01-01T05:00:00Z"), "v" : 299 } }
  • 15. 15 Example: Find Query • Find a flight status entry for United Airlines Flight 1234 – db.data.findOne({"callsign" : "UA7549"}) • Find a aircraft flying at less than 5000 feet – db.data.findOne({"events.a" : {$lt : 5000}}) • Set value of note field – db.data.update({"callsign" : "OY1949"}, {$set : {"note" : "spoke with captain"}})
  • 16. Retrieve One Document in Node.JS The Simple Things Don’t Always Seem Easy
  • 17. 17 The synchronous way var MongoClient = require('mongodb').MongoClient; var db = MongoClient.connect('mongodb://localhost:27017/adsb'); var col = db.collection('data'); var doc = col.findOne({"callsign" : "UA7549"}); console.log("Here is my doc: %j", doc); db.close();
  • 18. 18 The synchronous way var MongoClient = require('mongodb').MongoClient; var db = MongoClient.connect('mongodb://localhost:27017/adsb'); var col = db.collection('data'); var doc = col.findOne({"callsign" : "UA7549"}); console.log("Here is my doc: %j", doc); db.close();
  • 19. 19 It works this way in the mongoshell??? var col = db.getCollection("data"); var doc = col.findOne({"callsign" : "HR9368"}); printjson(doc);
  • 21. 21 Synchronous Programming time Func1 Func1 IO Func1 Func2 Func2 IO Func2
  • 22. 22 Asynchronous Programming time Func1 Func1 IO Func1Func2 Func2 IO Func2 IO Processing runs on separate threads in parallel with main processing thread
  • 23. 23 Callbacks col.findOne({"callsign" : "UA7549"}, function (err, doc) { assert.equal(null, err); console.log("Here is my doc: %j", doc); console.log(”All done!”); • Execute findOne • When it is done, call the callback function • Callback function takes two arguments – err – contains the error message or null – doc – the result of the findOne call • “All Done” will be printed before the “Here is my doc…”
  • 26. 26 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); Call Stack Driver API Callback Queue Event Loop
  • 27. 27 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); Call Stack Driver API Callback Queue Event Loop find1234()
  • 28. 28 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); Call Stack Driver API Callback Queue Event Loop find1234() col.findOne() col.findOne()
  • 29. 29 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); Call Stack Driver API Callback Queue Event Loop col.updateMany() col.findOne() col.updateMany()
  • 30. 30 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); Call Stack Driver API Callback Queue Event Loop col.insert() col.insert() col.updateMany() fo1_cb
  • 31. 31 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); Call Stack Driver API Callback Queue Event Loop console.log() col.updateMany() fo1_cb ins1_cb
  • 32. 32 Event Queue/Call Stack function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); function fo1_cb () {…} Call Stack Driver API Callback Queue Event Loop fo1_cb() col.updateMany() ins1_cb
  • 33. 33 Event Queue/Call Stack Call Stack Driver API Callback Queue Event Loop ins1_cb() up1_cb function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); function ins1_cb () {…}
  • 34. 34 Event Queue/Call Stack Call Stack Driver API Callback Queue Event Loop up1_cb() function find1234 () { col.findOne({_id: 1234}, fo1_cb); find1234(); col.updateMany({color: “blue”}, {$set : {w : 5}}, up1_cb); col.insert({product: 1234, cost: 99}, ins1_cb); console.log(“done”); function up1_cb () {…}
  • 35. Back to the findOne example
  • 36. 36 MongoDB Asynchronous Queries var MongoClient = require('mongodb').MongoClient, assert = require('assert'); MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); col.findOne({"callsign" : "UA7549"}, function (err, doc) { assert.equal(null, err); console.log("Here is my doc: %j", doc); db.close(); }); });
  • 37. 37 Asynchronously var MongoClient = require('mongodb').MongoClient, assert = require('assert'); MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); col.findOne({"callsign" : "UA7549"}, function (err, doc) { assert.equal(null, err); console.log("Here is my doc: %j", doc); db.close(); }); }); callback
  • 38. 38 Asynchronously var MongoClient = require('mongodb').MongoClient, assert = require('assert'); MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); col.findOne({"callsign" : "UA7549"}, function (err, doc) { assert.equal(null, err); console.log("Here is my doc: %j", doc); db.close(); }); }); callback
  • 39. 39 This gets ugly fast var MongoClient = require('mongodb').MongoClient, assert = require('assert'); var db = MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); col.findOne({"callsign" : "UA7549"}, function (err, doc) { assert.equal(null, err); console.log("Here is my doc: %j", doc); col.updateOne({"callsign" : "UA7549"}, {$set : {"note" : "Spoke with the pilot"}}, {}, function(err, result) { assert.equal(null, err); console.log("Note updated"); db.close(); }); }); });
  • 40. 40 Nested callbacks - yuck async1(function(input, result1) { async2(function(result2) { async3(function(result3) { async4(function(result4) { async5(function(output) { // do something with output }); }); }); }); })
  • 41. 41 Solutions • Break up into modules • Use a Flow Control library – async – Step • Promises
  • 42. 42 With Flow Control - Step Step ( function connectToMongoDB (err, db) { MongoClient.connect('mongodb:// localhost:27017/adsb', this); }, function findOneDoc(err, db) { if (err) console.log("Connect: %j", err); database = db; collection = db.collection('data'); collection.findOne(csQuery, {}, this); }, function updateDoc(err, doc) { if (err) console.log("Find One: %j", err); console.log("Here is my doc: %j", doc); collection.updateOne(csQuery, {$inc : {"timesViewed" : 1}},{},this); }, function findOneDoc2 (err, result) { if (err) console.log("Update error: %j", err); collection.findOne(csQuery, {}, this); }, function closeConnection(err, doc) { if (err) console.log("FindOne Doc: %j", err); console.log("Note updated: %j", doc); database.close(); } );
  • 43. 43 With Flow Control Step ( function connectToMongoDB (err, db) { MongoClient.connect('mongodb:// localhost:27017/adsb', this); }, function findOneDoc(err, db) { if (err) console.log("Connect: %j", err); database = db; collection = db.collection('data'); collection.findOne(csQuery, {}, this); }, function updateDoc(err, doc) { if (err) console.log("Find One: %j", err); console.log("Here is my doc: %j", doc); collection.updateOne(csQuery, {$inc : {"timesViewed" : 1}},{},this); }, function findOneDoc2 (err, result) { if (err) console.log("Update error: %j", err); collection.findOne(csQuery, {}, this); }, function closeConnection(err, doc) { if (err) console.log("FindOne Doc: %j", err); console.log("Note updated: %j", doc); database.close(); }
  • 44. 44 With Flow Control Step ( function connectToMongoDB (err, db) { MongoClient.connect('mongodb:// localhost:27017/adsb', this); }, function findOneDoc(err, db) { if (err) console.log("Connect: %j", err); database = db; collection = db.collection('data'); collection.findOne(csQuery, {}, this); }, function updateDoc(err, doc) { if (err) console.log("Find One: %j", err); console.log("Here is my doc: %j", doc); collection.updateOne(csQuery, {$inc : {"timesViewed" : 1}},{},this); }, function findOneDoc2 (err, result) { if (err) console.log("Update error: %j", err); collection.findOne(csQuery, {}, this); }, function closeConnection(err, doc) { if (err) console.log("FindOne Doc: %j", err); console.log("Note updated: %j", doc); database.close(); }
  • 45. 45 You can also execute in parallel Step ( function connectToMongoDB (err, db) { MongoClient.connect('mongodb://localhost:27017/adsb', this); }, function executeParallel (err, db) { if (err) console.log("Connect: %j", err); var collection = db.collection('data'); database = db; collection.findOne(csQuery, {}, this.parallel()); collection.updateOne(csQuery, {$inc : {"timesViewed" : 1}}, {}, this.parallel()); collection.findOne(csQuery, {}, this.parallel()); }, function closeConnection(err, doc1, upResult, doc2) { if (err) console.log("Error: %j", err); console.log("Here is doc1: %j", doc1); console.log("Incremented: %j", upResult); console.log("Here is doc2: %j", doc2); database.close(); } );
  • 46. How do you deal with multiple find results?
  • 47. 47 Find Many - Cursor • This works in the MongoShell var col = db.getCollection("data"); var cursor = col.find({"events.a" : {$gt : 5000}}); while (cursor.hasNext()) { printjson(cursor.next()); }
  • 48. 48 Find Many - Cursor • This works in the MongoShell var col = db.getCollection("data"); var cursor = col.find({"events.a" : {$gt : 5000}}); while (cursor.hasNext()) { printjson(cursor.next()); } • It does not work in Node.JS • The MongoDB driver retrieves documents in batches from MongoDB – Retrieving a new batch is asynchronous
  • 49. 49 Find Many - Streams MongoClient.connect("mongodb://localhost:27017/adsb", function (err, db) { var col = db.collection('data') var stream = col.find({"events.a" : {$gt : 5000}}).stream(); stream.on('data', function(doc) { console.log("Doc: %j", doc); }); stream.on('error', function (doc) { console.log("Query failed: %j", doc); }); stream.on('end', function() { console.log("All data retrieved."); db.close(); }); });
  • 50. 50 Find Many - Streams MongoClient.connect("mongodb://localhost:27017/adsb", function (err, db) { var col = db.collection('data') var stream = col.find({"events.a" : {$gt : 5000}}).stream(); stream.on('data', function(doc) { console.log("Doc: %j", doc); }); stream.on('error', function (doc) { console.log("Query failed: %j", doc); }); stream.on('end', function() { console.log("All data retrieved."); db.close(); }); }); ‘data’ callback invoked for each document
  • 51. 51 What about insert? MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); col.insert({x: 1, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Insert Complete"); db.close(); }); });
  • 52. 52 What if I have to insert 100M documents? MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); for (i = 1; i <= 100000000; i++) { col.insert({x: i, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Insert Complete"); }); } }); Let’s insert all 100,000,000 in parallel!!!!
  • 53. 53 What if I have to insert 100M documents? MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); for (i = 1; i <= 100000000; i++) { col.insert({x: i, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Insert Complete"); db.close(); }); } }); FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
  • 54. 54 Event Queue/Call Stack for (i = 1; i <= 100000000; i++) { col.insert({x: i, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Insert C…"); }); } Call Stack Driver API Callback Queue Event Loop
  • 55. 55 Event Queue/Call Stack for (i = 1; i <= 100000000; i++) { col.insert({x: i, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Insert C…"); db.close(); }); Call Stack Driver API Callback Queue Event Loop col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() col.insert()
  • 56. 56 Event Queue/Call Stack for (i = 1; i <= 100000000; i++) { col.insert({x: i, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Insert C…"); db.close(); }); Call Stack Driver API Callback Queue Event Loop col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() col.insert() FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
  • 57. 57 Let’s try 5 at a time var DOCS_TO_INSERT = 1000; var numInsertsRunning = 0; // number of insert threads var insertCount = 0; // number of documents inserted so far MongoClient.connect('mongodb://localhost:27017/adsb', function (err, db) { assert.equal(null, err); var col = db.collection('data'); for (i = 0; i < 5; i++) { ++numInsertsRunning; insertDocument(db, col, ++insertCount, i, function (err, result) { console.log("All ", DOCS_TO_INSERT, " documents inserted."); db.close(); }); } });
  • 58. 58 insertDocument function function insertDocument (db, col, docNum, threadNum, callback) { col.insert({x: ++insertCount, y: 2, z: 3}, {}, function (err, result) { assert.equal(null, err); console.log("Thread: ", threadNum, " inserted doc: ", docNum, "."); if (insertCount < DOCS_TO_INSERT) insertDocument(db, col, ++insertCount, threadNum, callback); else if (numInsertsRunning == 1) { numInsertsRunning--; callback(null, true); } else numInsertsRunning--; }); }
  • 59. 59 InsertDocument Callback Logic col.insert({x: ++insertCount, y: 2, z: 3}, function (err, result) { } Have all the documents been inserted? Call insertDocument again Are other inserts still running? Do nothing & decrement running thread count All inserts done Call the original callback Yes Yes No No
  • 60. 60 Bulk Inserts • The previous example was for illustrative purposes • MongoDB provides a buik write API that provides better performance for bulk writes • The bulk write API batches up writes – Batch writes with a single acknowledgement • Use collection.bulkWrite • Improve performance using multiple bulkWrite threads – Previous example will be identical – Replace collection.insert with collection.bulkWrite
  • 61. 61 Another word of caution • All my examples established a MongoDB connection and then closed it – This was for illustrative purposes • Don’t continuously open and close MongoDB connections. • Open a connection once once – Use that connection through the life of the program – Close it at the end
  • 62. 62 Summary • Asynchronous vs synchronous programming • Call stack, event loop, driver API • Flow control • Find, insert, update examples • Managing multiple parallel threads – bulk insert example • Learn from my mistakes and misconceptions