SlideShare a Scribd company logo
1 of 67
An introduction to the
node.js mongo driver
     Christian Amor Kvalheim
• Asynchronous Javascript platform built on
  top of V8
• Single-threaded
• Package manager
• Awesome
Hello World Server
var http = require('http');

http.createServer(
  function (req, res) {
    res.writeHead(200,
      {'Content-Type': 'text/plain'});
    res.end('Hello Worldn');
  }).listen(8124, "127.0.0.1");
Hello World Server
                                     Load the http library
var http = require('http');

http.createServer(
  function (req, res) {
    res.writeHead(200,
      {'Content-Type': 'text/plain'});
    res.end('Hello Worldn');
  }).listen(8124, "127.0.0.1");
Hello World Server
                                     Load the http library
var http = require('http');
                                     Set up the connection
http.createServer(                          handler
  function (req, res) {
    res.writeHead(200,
      {'Content-Type': 'text/plain'});
    res.end('Hello Worldn');
  }).listen(8124, "127.0.0.1");
How to get started

• Install node.js (from source or package)
• Install npm (node package manager)
• Create an empty directory
• npm install mongodb
• npm install express
Let’s do some code


• Using Express and Mongo
• Textmate basic.js
Picking it apart
var db = new Db('node-mongo-examples', new Server(host, port, {}),
{native_parser:false});




db.open(function(err, db) { ...
  .....
  app.listen(8124);




var app = express.createServer();

app.get('/', function(req, res){
  res.send('Hello World');
});
Picking it apart
  Creates a db using the js bson parser
var db = new Db('node-mongo-examples', new Server(host, port, {}),
{native_parser:false});




db.open(function(err, db) { ...
  .....
  app.listen(8124);




var app = express.createServer();

app.get('/', function(req, res){
  res.send('Hello World');
});
Picking it apart
  Creates a db using the js bson parser
var db = new Db('node-mongo-examples', new Server(host, port, {}),
{native_parser:false});



  Opens the connection to the db
db.open(function(err, db) { ...
  .....
  app.listen(8124);




var app = express.createServer();

app.get('/', function(req, res){
  res.send('Hello World');
});
Picking it apart
  Creates a db using the js bson parser
var db = new Db('node-mongo-examples', new Server(host, port, {}),
{native_parser:false});



  Opens the connection to the db
db.open(function(err, db) { ...
  .....
  app.listen(8124);


 The server is now running with access to
      the mongo server connection
var app = express.createServer();

app.get('/', function(req, res){
  res.send('Hello World');
});
Let’s add some meat


• CRUD operations
• Textmate basic_2.js
Picking it apart
// Create method
app.post('/location', function(req, res) {
  geoCodeDecorateObject(req.body.address, {description:req.body.description},
function(err, object) {
    db.collection('locations', function(err, collection) {

      // Insert doc
      collection.insert(object, {safe:true}, function(err, result) {

        // Fetch all docs for rendering of list
        collection.find({}).toArray(function(err, items) {
           res.render('./basic_2.jade', {locals: {locations:items}});
        })
      });
    });
  });
});
Picking it apart
Geo Encode Address
// Create method
app.post('/location', function(req, res) {
  geoCodeDecorateObject(req.body.address, {description:req.body.description},
function(err, object) {
    db.collection('locations', function(err, collection) {

      // Insert doc
      collection.insert(object, {safe:true}, function(err, result) {

        // Fetch all docs for rendering of list
        collection.find({}).toArray(function(err, items) {
           res.render('./basic_2.jade', {locals: {locations:items}});
        })
      });
    });
  });
});
Picking it apart
       Geo Encode Address
       // Create method
       app.post('/location', function(req, res) {
         geoCodeDecorateObject(req.body.address, {description:req.body.description},
       function(err, object) {
           db.collection('locations', function(err, collection) {

             // Insert doc
             collection.insert(object, {safe:true}, function(err, result) {

               // Fetch all docs for rendering of list
               collection.find({}).toArray(function(err, items) {
                  res.render('./basic_2.jade', {locals: {locations:items}});
               })

Insert record, safe ensures that we trap any
             });
           });
         });
   errors by doing a error check against
       });


                  mongodb
Picking it apart
     // Create method
     app.post('/location', function(req, res) {
       geoCodeDecorateObject(req.body.address, {description:req.body.description},
     function(err, object) {
         db.collection('locations', function(err, collection) {

           // Insert doc
           collection.insert(object, {safe:true}, function(err, result) {

             // Fetch all docs for rendering of list
             collection.find({}).toArray(function(err, items) {
                res.render('./basic_2.jade', {locals: {locations:items}});
             })
           });
         });
       });
     find all records from the locations
     });


collection. Find returns a cursor that allows
      for stepping through doucments
Safe or not

• Mongo Insert/Update/Delete are async
• 2nd call to lastError required to check for
  the success of the operation
• safe option ensures the second error call
• you can also run the driver in strict mode
Let’s add some meat


• CRUD operations
• Textmate basic_3.js
Picking it apart
// Delete method
app.del('/location', function(req, res) {
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {
    collection.remove({_id:id}, {safe:true}, function(err, numberOfDeletedRecords) {

       // Fetch all docs for rendering of list
      collection.find({}).toArray(function(err, items) {
         res.render('./basic_3.jade', {locals: {locations:items}});
      })
    })
  });
});
Picking it apart
                                                  Convert hex string to
// Delete method                                       objectID
app.del('/location', function(req, res) {
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {
    collection.remove({_id:id}, {safe:true}, function(err, numberOfDeletedRecords) {

       // Fetch all docs for rendering of list
      collection.find({}).toArray(function(err, items) {
         res.render('./basic_3.jade', {locals: {locations:items}});
      })
    })
  });
});
Picking it apart
                                                  Convert hex string to
// Delete method                                       objectID
app.del('/location', function(req, res) {
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {
    collection.remove({_id:id}, {safe:true}, function(err, numberOfDeletedRecords) {

       // Fetch all docs for rendering of list
      collection.find({}).toArray(function(err, items) {
         res.render('./basic_3.jade', {locals: {locations:items}});

    })
      })
                Remove the document using the specific id
  });
});
                         passed in, using safe.
Let’s add some meat


• CRUD operations
• Textmate basic_4.js
Picking it apart
// Get method
app.get('/location', function(req, res) {
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {

    collection.findOne({_id:id}, function(err, item) {

      // Fetch all docs for rendering of list
      collection.find({}).toArray(function(err, items) {
         res.render('./basic_4.jade', {locals: {locations:items, location:item}});
      })
    })
  });
});
Picking it apart
                                  Convert hex string to
// Get method
app.get('/location', function(req, res) {
                                          objectID
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {

    collection.findOne({_id:id}, function(err, item) {

      // Fetch all docs for rendering of list
      collection.find({}).toArray(function(err, items) {
         res.render('./basic_4.jade', {locals: {locations:items, location:item}});
      })
    })
  });
});
Picking it apart
                                  Convert hex string to
// Get method
app.get('/location', function(req, res) {
                                          objectID
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {

    collection.findOne({_id:id}, function(err, item) {

      // Fetch all docs for rendering of list
      collection.find({}).toArray(function(err, items) {
         res.render('./basic_4.jade', {locals: {locations:items, location:item}});

    })
      })
                          Locate one document by id
  });
});
Let’s add some meat


• CRUD operations
• Textmate basic_5.js
Picking it apart
// Update method
app.put('/location', function(req, res) {
  var id = ObjectID.createFromHexString(req.body.id);
  db.collection('locations', function(err, collection) {

   collection.findOne({_id:id}, function(err, object) {
     object.description = req.body.description;
     object.address = req.body.address;

     geoCodeDecorateObject(req.body.address, object, function(err, object) {

        collection.update({_id:object._id}, object, {safe:true}, function(err,
numberOfUpdatedObjects) {

            // Fetch all docs for rendering of list
            collection.find({}).toArray(function(err, items) {
               res.render('./basic_5.jade', {locals: {locations:items}});
            })
          })
     })
Picking it apart
// Update method
app.put('/location', function(req, res) {
                                                 Locate object we wish
  var id = ObjectID.createFromHexString(req.body.id);
                                                       to modify
  db.collection('locations', function(err, collection) {

   collection.findOne({_id:id}, function(err, object) {
     object.description = req.body.description;
     object.address = req.body.address;

     geoCodeDecorateObject(req.body.address, object, function(err, object) {

        collection.update({_id:object._id}, object, {safe:true}, function(err,
numberOfUpdatedObjects) {

            // Fetch all docs for rendering of list
            collection.find({}).toArray(function(err, items) {
               res.render('./basic_5.jade', {locals: {locations:items}});
            })
          })
     })
Picking it apart
// Update method
app.put('/location', function(req, res) {
                                                 Locate object we wish
  var id = ObjectID.createFromHexString(req.body.id);
                                                       to modify
  db.collection('locations', function(err, collection) {

   collection.findOne({_id:id}, function(err, object) {
     object.description = req.body.description;
     object.address = req.body.address;

     geoCodeDecorateObject(req.body.address, object, function(err, object) {

        collection.update({_id:object._id}, object, {safe:true}, function(err,
numberOfUpdatedObjects) {

            // Fetch all docs for rendering of list
            collection.find({}).toArray(function(err, items) {
               res.render('./basic_5.jade', {locals: {locations:items}});
            })

     })
          })   Update document using the id to select
                     what document to update
Let’s add some meat


• Final with search
• Textmate basic_6.js
Picking it apart
db.open(function(err, db) {
  if(err) throw err

  // !!! CHANGE
  db.ensureIndex("locations", {loc:"2d"}, function(err, result) {
    if(err) throw err

    app.listen(8124);
  })
});
Picking it apart
db.open(function(err, db) {
  if(err) throw err

  // !!! CHANGE
  db.ensureIndex("locations", {loc:"2d"}, function(err, result) {
    if(err) throw err

    app.listen(8124);
  })
});    Ensures there is a 2d geospatial index on
       the attribute loc on any document in the
                  locations collection
Picking it apart
var geoCodeDecorateObject = function(address, object, callback) {
  var googleGeoCodeApi = {host: 'maps.googleapis.com',
    port: 80,path: '/maps/api/geocode/json?sensor=false&address=' +
escape(address),
    method: 'GET' };

  var clientReq = http.get(googleGeoCodeApi, function(clientRes) {
    var data = [];
    clientRes.on('data', function(chunk) {
      data.push(chunk.toString());
    });
    clientRes.on('end', function() {
      var googleObject = JSON.parse(data.join(''));

     object.address = address;
     object.geodata = googleObject.results.pop();

      // !!! CHANGE
      object.loc = {long:object.geodata.geometry.location.lng,
lat:object.geodata.geometry.location.lat};

     callback(null, object);
   });
Picking it apart
var geoCodeDecorateObject = function(address, object, callback) {
  var googleGeoCodeApi = {host: 'maps.googleapis.com',
    port: 80,path: '/maps/api/geocode/json?sensor=false&address=' +
escape(address),
    method: 'GET' };

  var clientReq = http.get(googleGeoCodeApi, function(clientRes) {
    var data = [];
    clientRes.on('data', function(chunk) {
      data.push(chunk.toString());
                                                          We are adding a loc
    });
    clientRes.on('end', function() {
                                                             attribute to all
      var googleObject = JSON.parse(data.join(''));
                                                            documents with
     object.address = address;
     object.geodata = googleObject.results.pop();            longtidude and
      // !!! CHANGE                                       latitude in the right
      object.loc = {long:object.geodata.geometry.location.lng,
lat:object.geodata.geometry.location.lat};               order for mongodb to
     callback(null, object);
   });
                                                                  search
Picking it apart
// !!! CHANGE
// Search option
app.post('/search', function(req, res) {
  geoCodeDecorateObject(req.body.address, {}, function(err, object) {
    // Unpack geo object
    var long = object.geodata.geometry.location.lng;
    var lat = object.geodata.geometry.location.lat

    db.collection('locations', function(err, collection) {
      collection.find({loc : {'$near': [long, lat], '$maxDistance':
parseFloat(req.body.distance)}}).toArray(function(err, geoItems) {
        // Fetch all docs for rendering of list
        collection.find({}).toArray(function(err, items) {
           res.render('./basic_6.jade', {locals: {locations:items,
results:geoItems}});
        })
      });
    });
  });
});
Picking it apart
                                                  Encode address for
// !!! CHANGE
// Search option                                      searching
app.post('/search', function(req, res) {
  geoCodeDecorateObject(req.body.address, {}, function(err, object) {
    // Unpack geo object
    var long = object.geodata.geometry.location.lng;
    var lat = object.geodata.geometry.location.lat

    db.collection('locations', function(err, collection) {
      collection.find({loc : {'$near': [long, lat], '$maxDistance':
parseFloat(req.body.distance)}}).toArray(function(err, geoItems) {
        // Fetch all docs for rendering of list
        collection.find({}).toArray(function(err, items) {
           res.render('./basic_6.jade', {locals: {locations:items,
results:geoItems}});
        })
      });
    });
  });
});
Picking it apart
                                                  Encode address for
// !!! CHANGE
// Search option                                      searching
app.post('/search', function(req, res) {
  geoCodeDecorateObject(req.body.address, {}, function(err, object) {
    // Unpack geo object
    var long = object.geodata.geometry.location.lng;
    var lat = object.geodata.geometry.location.lat

    db.collection('locations', function(err, collection) {
      collection.find({loc : {'$near': [long, lat], '$maxDistance':
parseFloat(req.body.distance)}}).toArray(function(err, geoItems) {
        // Fetch all docs for rendering of list
        collection.find({}).toArray(function(err, items) {
           res.render('./basic_6.jade', {locals: {locations:items,
results:geoItems}});
        })
      });
                    Search for all items $near our address at
    });
  });
                                    $maxDistance
});
Other features


•   Cursors
•   Grid FS
Cursors

• toArray Function
• each Function
• streamRecords Function
toArray

collection.find().toArray(function(err, documents){
  test.deepEqual([1, 2, 3], documents[0].b);
  // Let's close the db
  test.done();
});
toArray
                       Fetches all docs in one go
                        for the query. Use with
                                caution
collection.find().toArray(function(err, documents){
  test.deepEqual([1, 2, 3], documents[0].b);
  // Let's close the db
  test.done();
});
each

collection.find({}, {'sort':[['age', 1]]}).each(function(err, item){
    if(item != null) {
       // Do work
    } else {
       // Finished
    }
});
each
                                  Fetches docs in batches and
                                  allows iteration over results

collection.find({}, {'sort':[['age', 1]]}).each(function(err, item){
    if(item != null) {
       // Do work
    } else {
       // Finished
    }
});
each
                                  Fetches docs in batches and
                                  allows iteration over results

collection.find({}, {'sort':[['age', 1]]}).each(function(err, item){
    if(item != null) {
       // Do work
    } else {
       // Finished
    }
});
                            Returns null when no more
                                 results available
streamRecords
  var stream = collection.find({}, {'limit' :
  3}).streamRecords();

stream.on('end', function() {
  // No more results in the pipe
});

stream.on('data',function(data){
  // Item
});
streamRecords
  var stream = collection.find({}, {'limit' :
  3}).streamRecords();

stream.on('end', function() {
  // No more results in the pipe
});

stream.on('data',function(data){
  // Item
});

                          When an item is ready the
                           event ‘data’ is triggered
streamRecords
  var stream = collection.find({}, {'limit' :
  3}).streamRecords();
                                      When no more items
stream.on('end', function() {            are available
  // No more results in the pipe
});

stream.on('data',function(data){
  // Item
});

                          When an item is ready the
                           event ‘data’ is triggered
streamRecords
  var stream = collection.find({}, {'limit' :
  3}).streamRecords();
                                      When no more items
stream.on('end', function() {            are available
  // No more results in the pipe
});


                                      REFERED
                                     P
stream.on('data',function(data){
  // Item
});

                          When an item is ready the
                           event ‘data’ is triggered
Grid FS

• Write and read a file
• Stream a file
Write a file
var gridStore = new GridStore(client, 'test_gs_writing_file', 'w');

gridStore.open(function(err, gridStore) {

gridStore.writeFile('./test_gs_weird_bug.png', function(err, gridStore) {




  GridStore.read(client, 'test_gs_writing_file', function(err, fileData) {
  });
Write a file
var gridStore = new GridStore(client, 'test_gs_writing_file', 'w');

gridStore.open(function(err, gridStore) {

gridStore.writeFile('./test_gs_weird_bug.png', function(err, gridStore) {


                       Writes the file in chunks to
                       mongodb (avoids freezing the
                          eventloop in node.js)

  GridStore.read(client, 'test_gs_writing_file', function(err, fileData) {
  });
Write a file
var gridStore = new GridStore(client, 'test_gs_writing_file', 'w');

gridStore.open(function(err, gridStore) {

gridStore.writeFile('./test_gs_weird_bug.png', function(err, gridStore) {


                       Writes the file in chunks to
                       mongodb (avoids freezing the
                          eventloop in node.js)

  GridStore.read(client, 'test_gs_writing_file', function(err, fileData) {
  });



                        Read the whole file. Careful with the
                                    memory
Stream a file
var gridStore = new GridStore(client, "test_gs_read_stream", "r");

gridStore.open(function(err, gs) {
  var stream = gs.stream(true);




 stream.on("data", function(chunk) {
   // Received a chunk of data
 });




  stream.on("end", function() {
    // Finished streaming
  });
});
Stream a file
var gridStore = new GridStore(client, "test_gs_read_stream", "r");

gridStore.open(function(err, gs) {
  var stream = gs.stream(true);

                   Receive a chunk and do something
 stream.on("data", function(chunk) {
   // Received a chunk of data
 });




  stream.on("end", function() {
    // Finished streaming
  });
});
Stream a file
var gridStore = new GridStore(client, "test_gs_read_stream", "r");

gridStore.open(function(err, gs) {
  var stream = gs.stream(true);

                   Receive a chunk and do something
 stream.on("data", function(chunk) {
   // Received a chunk of data
 });
                    Finshed stream the file

  stream.on("end", function() {
    // Finished streaming
  });
});
Stream a file
var gridStore = new GridStore(client, "test_gs_read_stream", "r");

gridStore.open(function(err, gs) {
  var stream = gs.stream(true);

                   Receive a chunk and do something
 stream.on("data", function(chunk) {
   // Received a chunk of data
 });
                    Finshed stream the file

  stream.on("end", function() {
    // Finished streaming              PR EFE RED
  });
});
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i});
}




collection.count(function(err, count) {
  // count is > 0 <= 100
});
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i});
}


                    All executed in parallel, non-
                   deterministic end of execution
collection.count(function(err, count) {
  // count is > 0 <= 100
});
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i});
}


                    All executed in parallel, non-
                   deterministic end of execution
collection.count(function(err, count) {
  // count is > 0 <= 100
});

                   All inserts MAY have been written
                   to disk so passes most of the time.
                        But with Pooling NO WAY
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i}, {safe:true}, function(err, result) {
    // Do something
  });
}

??????????????????????????????
collection.count(function(err, count) {
  // count is > 0 <= 100
});
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i}, {safe:true}, function(err, result) {
    // Do something
  });
}                         How do we handle the callbacks
??????????????????????????????
collection.count(function(err, count) {
  // count is > 0 <= 100
});
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i}, {safe:true}, function(err, result) {
    // Do something
  });
}                         How do we handle the callbacks
??????????????????????????????
collection.count(function(err, count) {
  // count is > 0 <= 100
});


                      How do we get to this code ??????
Typical starting problems
for(var i = 0; i < 100; i++) {
  collection.insert({'i':i}, {safe:true}, function(err, result) {
    // Do something
  });
}                         How do we handle the callbacks
??????????????????????????????
collection.count(function(err, count) {
  // count is > 0 <= 100
});


                      How do we get to this code ??????

       Many possible solutions
My Choosen Solution
                https://github.com/creationix/step
    Step(
      function insert() {
         var group = this.group();
         for(var i = 0; i < 100; i++) {
           collection.insert({'i':i}, {safe:true}, group());
         }
      },




    function finished() {
      collection.count(function(err, count) {
        // Count is 100 :)
      });
    }
)
My Choosen Solution
                https://github.com/creationix/step
    Step(
      function insert() {
         var group = this.group();
         for(var i = 0; i < 100; i++) {
           collection.insert({'i':i}, {safe:true}, group());
         }
      },                 Ensures all the inserts are finished
                          before calling the next function
    function finished() {
      collection.count(function(err, count) {
        // Count is 100 :)
      });
    }
)
My Choosen Solution
                https://github.com/creationix/step
    Step(
      function insert() {
         var group = this.group();
         for(var i = 0; i < 100; i++) {
           collection.insert({'i':i}, {safe:true}, group());
         }
      },                 Ensures all the inserts are finished
                          before calling the next function
    function finished() {
      collection.count(function(err, count) {
        // Count is 100 :)
      });
    }
)                         When all inserts are done :)
DONE
                   Code on
https://github.com/christkv/mongodb-hamburg

More Related Content

What's hot

Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2
RORLAB
 
Hd insight programming
Hd insight programmingHd insight programming
Hd insight programming
Casear Chu
 

What's hot (20)

Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Config BuildConfig
Config BuildConfigConfig BuildConfig
Config BuildConfig
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEB
 
Using Arbor/ RGraph JS libaries for Data Visualisation
Using Arbor/ RGraph JS libaries for Data VisualisationUsing Arbor/ RGraph JS libaries for Data Visualisation
Using Arbor/ RGraph JS libaries for Data Visualisation
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 
Writing Your App Swiftly
Writing Your App SwiftlyWriting Your App Swiftly
Writing Your App Swiftly
 
Minimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team ProductivityMinimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team Productivity
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applications
 
Elm: give it a try
Elm: give it a tryElm: give it a try
Elm: give it a try
 
Cycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveCycle.js: Functional and Reactive
Cycle.js: Functional and Reactive
 
Hidden rocks in Oracle ADF
Hidden rocks in Oracle ADFHidden rocks in Oracle ADF
Hidden rocks in Oracle ADF
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
 
Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2
 
Hd insight programming
Hd insight programmingHd insight programming
Hd insight programming
 
Hello Swift Final 5/5 - Structures and Classes
Hello Swift Final 5/5 - Structures and ClassesHello Swift Final 5/5 - Structures and Classes
Hello Swift Final 5/5 - Structures and Classes
 
Lodash js
Lodash jsLodash js
Lodash js
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
 

Viewers also liked

Building Applications using MongoDB, Node.js and Socket.io
Building Applications using MongoDB, Node.js and Socket.ioBuilding Applications using MongoDB, Node.js and Socket.io
Building Applications using MongoDB, Node.js and Socket.io
MongoDB
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
Mohammad Qureshi
 

Viewers also liked (12)

Building Applications using MongoDB, Node.js and Socket.io
Building Applications using MongoDB, Node.js and Socket.ioBuilding Applications using MongoDB, Node.js and Socket.io
Building Applications using MongoDB, Node.js and Socket.io
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
Knonex
KnonexKnonex
Knonex
 
Python and pandas as back end to real-time data driven applications by Giovan...
Python and pandas as back end to real-time data driven applications by Giovan...Python and pandas as back end to real-time data driven applications by Giovan...
Python and pandas as back end to real-time data driven applications by Giovan...
 
Geospatial Indexing and Querying with MongoDB
Geospatial Indexing and Querying with MongoDBGeospatial Indexing and Querying with MongoDB
Geospatial Indexing and Querying with MongoDB
 
Introduction to node js - From "hello world" to deploying on azure
Introduction to node js - From "hello world" to deploying on azureIntroduction to node js - From "hello world" to deploying on azure
Introduction to node js - From "hello world" to deploying on azure
 
NodeJS - Server Side JS
NodeJS - Server Side JS NodeJS - Server Side JS
NodeJS - Server Side JS
 
Best node js course
Best node js courseBest node js course
Best node js course
 
7 Stages of Scaling Web Applications
7 Stages of Scaling Web Applications7 Stages of Scaling Web Applications
7 Stages of Scaling Web Applications
 
NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Better Software—Faster: Ten Best Practices from Sequoia's Microservices Summit
Better Software—Faster: Ten Best Practices from Sequoia's Microservices SummitBetter Software—Faster: Ten Best Practices from Sequoia's Microservices Summit
Better Software—Faster: Ten Best Practices from Sequoia's Microservices Summit
 

Similar to Node js mongodriver

HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
Night Sailer
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
stasimus
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
偉格 高
 
node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascript
Eldar Djafarov
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
Sven Haiges
 

Similar to Node js mongodriver (20)

Dpilot - Source Code with Snapshots
Dpilot - Source Code with SnapshotsDpilot - Source Code with Snapshots
Dpilot - Source Code with Snapshots
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
Mongoskin - Guilin
Mongoskin - GuilinMongoskin - Guilin
Mongoskin - Guilin
 
NoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love StoryNoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love Story
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!
 
From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 
Softshake - Offline applications
Softshake - Offline applicationsSoftshake - Offline applications
Softshake - Offline applications
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
Ajax - a quick introduction
Ajax - a quick introductionAjax - a quick introduction
Ajax - a quick introduction
 
node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascript
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 

More from christkv

Storage talk
Storage talkStorage talk
Storage talk
christkv
 

More from christkv (9)

From SQL to MongoDB
From SQL to MongoDBFrom SQL to MongoDB
From SQL to MongoDB
 
New in MongoDB 2.6
New in MongoDB 2.6New in MongoDB 2.6
New in MongoDB 2.6
 
Lessons from 4 years of driver develoment
Lessons from 4 years of driver develomentLessons from 4 years of driver develoment
Lessons from 4 years of driver develoment
 
Storage talk
Storage talkStorage talk
Storage talk
 
Mongo db ecommerce
Mongo db ecommerceMongo db ecommerce
Mongo db ecommerce
 
Cdr stats-vo ip-analytics_solution_mongodb_meetup
Cdr stats-vo ip-analytics_solution_mongodb_meetupCdr stats-vo ip-analytics_solution_mongodb_meetup
Cdr stats-vo ip-analytics_solution_mongodb_meetup
 
Mongodb intro
Mongodb introMongodb intro
Mongodb intro
 
Schema design
Schema designSchema design
Schema design
 
Node.js and ruby
Node.js and rubyNode.js and ruby
Node.js and ruby
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 

Node js mongodriver

  • 1. An introduction to the node.js mongo driver Christian Amor Kvalheim
  • 2. • Asynchronous Javascript platform built on top of V8 • Single-threaded • Package manager • Awesome
  • 3. Hello World Server var http = require('http'); http.createServer( function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); }).listen(8124, "127.0.0.1");
  • 4. Hello World Server Load the http library var http = require('http'); http.createServer( function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); }).listen(8124, "127.0.0.1");
  • 5. Hello World Server Load the http library var http = require('http'); Set up the connection http.createServer( handler function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); }).listen(8124, "127.0.0.1");
  • 6. How to get started • Install node.js (from source or package) • Install npm (node package manager) • Create an empty directory • npm install mongodb • npm install express
  • 7. Let’s do some code • Using Express and Mongo • Textmate basic.js
  • 8. Picking it apart var db = new Db('node-mongo-examples', new Server(host, port, {}), {native_parser:false}); db.open(function(err, db) { ... ..... app.listen(8124); var app = express.createServer(); app.get('/', function(req, res){ res.send('Hello World'); });
  • 9. Picking it apart Creates a db using the js bson parser var db = new Db('node-mongo-examples', new Server(host, port, {}), {native_parser:false}); db.open(function(err, db) { ... ..... app.listen(8124); var app = express.createServer(); app.get('/', function(req, res){ res.send('Hello World'); });
  • 10. Picking it apart Creates a db using the js bson parser var db = new Db('node-mongo-examples', new Server(host, port, {}), {native_parser:false}); Opens the connection to the db db.open(function(err, db) { ... ..... app.listen(8124); var app = express.createServer(); app.get('/', function(req, res){ res.send('Hello World'); });
  • 11. Picking it apart Creates a db using the js bson parser var db = new Db('node-mongo-examples', new Server(host, port, {}), {native_parser:false}); Opens the connection to the db db.open(function(err, db) { ... ..... app.listen(8124); The server is now running with access to the mongo server connection var app = express.createServer(); app.get('/', function(req, res){ res.send('Hello World'); });
  • 12. Let’s add some meat • CRUD operations • Textmate basic_2.js
  • 13. Picking it apart // Create method app.post('/location', function(req, res) { geoCodeDecorateObject(req.body.address, {description:req.body.description}, function(err, object) { db.collection('locations', function(err, collection) { // Insert doc collection.insert(object, {safe:true}, function(err, result) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_2.jade', {locals: {locations:items}}); }) }); }); }); });
  • 14. Picking it apart Geo Encode Address // Create method app.post('/location', function(req, res) { geoCodeDecorateObject(req.body.address, {description:req.body.description}, function(err, object) { db.collection('locations', function(err, collection) { // Insert doc collection.insert(object, {safe:true}, function(err, result) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_2.jade', {locals: {locations:items}}); }) }); }); }); });
  • 15. Picking it apart Geo Encode Address // Create method app.post('/location', function(req, res) { geoCodeDecorateObject(req.body.address, {description:req.body.description}, function(err, object) { db.collection('locations', function(err, collection) { // Insert doc collection.insert(object, {safe:true}, function(err, result) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_2.jade', {locals: {locations:items}}); }) Insert record, safe ensures that we trap any }); }); }); errors by doing a error check against }); mongodb
  • 16. Picking it apart // Create method app.post('/location', function(req, res) { geoCodeDecorateObject(req.body.address, {description:req.body.description}, function(err, object) { db.collection('locations', function(err, collection) { // Insert doc collection.insert(object, {safe:true}, function(err, result) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_2.jade', {locals: {locations:items}}); }) }); }); }); find all records from the locations }); collection. Find returns a cursor that allows for stepping through doucments
  • 17. Safe or not • Mongo Insert/Update/Delete are async • 2nd call to lastError required to check for the success of the operation • safe option ensures the second error call • you can also run the driver in strict mode
  • 18. Let’s add some meat • CRUD operations • Textmate basic_3.js
  • 19. Picking it apart // Delete method app.del('/location', function(req, res) { var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.remove({_id:id}, {safe:true}, function(err, numberOfDeletedRecords) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_3.jade', {locals: {locations:items}}); }) }) }); });
  • 20. Picking it apart Convert hex string to // Delete method objectID app.del('/location', function(req, res) { var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.remove({_id:id}, {safe:true}, function(err, numberOfDeletedRecords) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_3.jade', {locals: {locations:items}}); }) }) }); });
  • 21. Picking it apart Convert hex string to // Delete method objectID app.del('/location', function(req, res) { var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.remove({_id:id}, {safe:true}, function(err, numberOfDeletedRecords) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_3.jade', {locals: {locations:items}}); }) }) Remove the document using the specific id }); }); passed in, using safe.
  • 22. Let’s add some meat • CRUD operations • Textmate basic_4.js
  • 23. Picking it apart // Get method app.get('/location', function(req, res) { var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.findOne({_id:id}, function(err, item) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_4.jade', {locals: {locations:items, location:item}}); }) }) }); });
  • 24. Picking it apart Convert hex string to // Get method app.get('/location', function(req, res) { objectID var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.findOne({_id:id}, function(err, item) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_4.jade', {locals: {locations:items, location:item}}); }) }) }); });
  • 25. Picking it apart Convert hex string to // Get method app.get('/location', function(req, res) { objectID var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.findOne({_id:id}, function(err, item) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_4.jade', {locals: {locations:items, location:item}}); }) }) Locate one document by id }); });
  • 26. Let’s add some meat • CRUD operations • Textmate basic_5.js
  • 27. Picking it apart // Update method app.put('/location', function(req, res) { var id = ObjectID.createFromHexString(req.body.id); db.collection('locations', function(err, collection) { collection.findOne({_id:id}, function(err, object) { object.description = req.body.description; object.address = req.body.address; geoCodeDecorateObject(req.body.address, object, function(err, object) { collection.update({_id:object._id}, object, {safe:true}, function(err, numberOfUpdatedObjects) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_5.jade', {locals: {locations:items}}); }) }) })
  • 28. Picking it apart // Update method app.put('/location', function(req, res) { Locate object we wish var id = ObjectID.createFromHexString(req.body.id); to modify db.collection('locations', function(err, collection) { collection.findOne({_id:id}, function(err, object) { object.description = req.body.description; object.address = req.body.address; geoCodeDecorateObject(req.body.address, object, function(err, object) { collection.update({_id:object._id}, object, {safe:true}, function(err, numberOfUpdatedObjects) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_5.jade', {locals: {locations:items}}); }) }) })
  • 29. Picking it apart // Update method app.put('/location', function(req, res) { Locate object we wish var id = ObjectID.createFromHexString(req.body.id); to modify db.collection('locations', function(err, collection) { collection.findOne({_id:id}, function(err, object) { object.description = req.body.description; object.address = req.body.address; geoCodeDecorateObject(req.body.address, object, function(err, object) { collection.update({_id:object._id}, object, {safe:true}, function(err, numberOfUpdatedObjects) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_5.jade', {locals: {locations:items}}); }) }) }) Update document using the id to select what document to update
  • 30. Let’s add some meat • Final with search • Textmate basic_6.js
  • 31. Picking it apart db.open(function(err, db) { if(err) throw err // !!! CHANGE db.ensureIndex("locations", {loc:"2d"}, function(err, result) { if(err) throw err app.listen(8124); }) });
  • 32. Picking it apart db.open(function(err, db) { if(err) throw err // !!! CHANGE db.ensureIndex("locations", {loc:"2d"}, function(err, result) { if(err) throw err app.listen(8124); }) }); Ensures there is a 2d geospatial index on the attribute loc on any document in the locations collection
  • 33. Picking it apart var geoCodeDecorateObject = function(address, object, callback) { var googleGeoCodeApi = {host: 'maps.googleapis.com', port: 80,path: '/maps/api/geocode/json?sensor=false&address=' + escape(address), method: 'GET' }; var clientReq = http.get(googleGeoCodeApi, function(clientRes) { var data = []; clientRes.on('data', function(chunk) { data.push(chunk.toString()); }); clientRes.on('end', function() { var googleObject = JSON.parse(data.join('')); object.address = address; object.geodata = googleObject.results.pop(); // !!! CHANGE object.loc = {long:object.geodata.geometry.location.lng, lat:object.geodata.geometry.location.lat}; callback(null, object); });
  • 34. Picking it apart var geoCodeDecorateObject = function(address, object, callback) { var googleGeoCodeApi = {host: 'maps.googleapis.com', port: 80,path: '/maps/api/geocode/json?sensor=false&address=' + escape(address), method: 'GET' }; var clientReq = http.get(googleGeoCodeApi, function(clientRes) { var data = []; clientRes.on('data', function(chunk) { data.push(chunk.toString()); We are adding a loc }); clientRes.on('end', function() { attribute to all var googleObject = JSON.parse(data.join('')); documents with object.address = address; object.geodata = googleObject.results.pop(); longtidude and // !!! CHANGE latitude in the right object.loc = {long:object.geodata.geometry.location.lng, lat:object.geodata.geometry.location.lat}; order for mongodb to callback(null, object); }); search
  • 35. Picking it apart // !!! CHANGE // Search option app.post('/search', function(req, res) { geoCodeDecorateObject(req.body.address, {}, function(err, object) { // Unpack geo object var long = object.geodata.geometry.location.lng; var lat = object.geodata.geometry.location.lat db.collection('locations', function(err, collection) { collection.find({loc : {'$near': [long, lat], '$maxDistance': parseFloat(req.body.distance)}}).toArray(function(err, geoItems) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_6.jade', {locals: {locations:items, results:geoItems}}); }) }); }); }); });
  • 36. Picking it apart Encode address for // !!! CHANGE // Search option searching app.post('/search', function(req, res) { geoCodeDecorateObject(req.body.address, {}, function(err, object) { // Unpack geo object var long = object.geodata.geometry.location.lng; var lat = object.geodata.geometry.location.lat db.collection('locations', function(err, collection) { collection.find({loc : {'$near': [long, lat], '$maxDistance': parseFloat(req.body.distance)}}).toArray(function(err, geoItems) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_6.jade', {locals: {locations:items, results:geoItems}}); }) }); }); }); });
  • 37. Picking it apart Encode address for // !!! CHANGE // Search option searching app.post('/search', function(req, res) { geoCodeDecorateObject(req.body.address, {}, function(err, object) { // Unpack geo object var long = object.geodata.geometry.location.lng; var lat = object.geodata.geometry.location.lat db.collection('locations', function(err, collection) { collection.find({loc : {'$near': [long, lat], '$maxDistance': parseFloat(req.body.distance)}}).toArray(function(err, geoItems) { // Fetch all docs for rendering of list collection.find({}).toArray(function(err, items) { res.render('./basic_6.jade', {locals: {locations:items, results:geoItems}}); }) }); Search for all items $near our address at }); }); $maxDistance });
  • 38. Other features • Cursors • Grid FS
  • 39. Cursors • toArray Function • each Function • streamRecords Function
  • 40. toArray collection.find().toArray(function(err, documents){ test.deepEqual([1, 2, 3], documents[0].b); // Let's close the db test.done(); });
  • 41. toArray Fetches all docs in one go for the query. Use with caution collection.find().toArray(function(err, documents){ test.deepEqual([1, 2, 3], documents[0].b); // Let's close the db test.done(); });
  • 42. each collection.find({}, {'sort':[['age', 1]]}).each(function(err, item){ if(item != null) { // Do work } else { // Finished } });
  • 43. each Fetches docs in batches and allows iteration over results collection.find({}, {'sort':[['age', 1]]}).each(function(err, item){ if(item != null) { // Do work } else { // Finished } });
  • 44. each Fetches docs in batches and allows iteration over results collection.find({}, {'sort':[['age', 1]]}).each(function(err, item){ if(item != null) { // Do work } else { // Finished } }); Returns null when no more results available
  • 45. streamRecords var stream = collection.find({}, {'limit' : 3}).streamRecords(); stream.on('end', function() { // No more results in the pipe }); stream.on('data',function(data){ // Item });
  • 46. streamRecords var stream = collection.find({}, {'limit' : 3}).streamRecords(); stream.on('end', function() { // No more results in the pipe }); stream.on('data',function(data){ // Item }); When an item is ready the event ‘data’ is triggered
  • 47. streamRecords var stream = collection.find({}, {'limit' : 3}).streamRecords(); When no more items stream.on('end', function() { are available // No more results in the pipe }); stream.on('data',function(data){ // Item }); When an item is ready the event ‘data’ is triggered
  • 48. streamRecords var stream = collection.find({}, {'limit' : 3}).streamRecords(); When no more items stream.on('end', function() { are available // No more results in the pipe }); REFERED P stream.on('data',function(data){ // Item }); When an item is ready the event ‘data’ is triggered
  • 49. Grid FS • Write and read a file • Stream a file
  • 50. Write a file var gridStore = new GridStore(client, 'test_gs_writing_file', 'w'); gridStore.open(function(err, gridStore) { gridStore.writeFile('./test_gs_weird_bug.png', function(err, gridStore) { GridStore.read(client, 'test_gs_writing_file', function(err, fileData) { });
  • 51. Write a file var gridStore = new GridStore(client, 'test_gs_writing_file', 'w'); gridStore.open(function(err, gridStore) { gridStore.writeFile('./test_gs_weird_bug.png', function(err, gridStore) { Writes the file in chunks to mongodb (avoids freezing the eventloop in node.js) GridStore.read(client, 'test_gs_writing_file', function(err, fileData) { });
  • 52. Write a file var gridStore = new GridStore(client, 'test_gs_writing_file', 'w'); gridStore.open(function(err, gridStore) { gridStore.writeFile('./test_gs_weird_bug.png', function(err, gridStore) { Writes the file in chunks to mongodb (avoids freezing the eventloop in node.js) GridStore.read(client, 'test_gs_writing_file', function(err, fileData) { }); Read the whole file. Careful with the memory
  • 53. Stream a file var gridStore = new GridStore(client, "test_gs_read_stream", "r"); gridStore.open(function(err, gs) { var stream = gs.stream(true); stream.on("data", function(chunk) { // Received a chunk of data }); stream.on("end", function() { // Finished streaming }); });
  • 54. Stream a file var gridStore = new GridStore(client, "test_gs_read_stream", "r"); gridStore.open(function(err, gs) { var stream = gs.stream(true); Receive a chunk and do something stream.on("data", function(chunk) { // Received a chunk of data }); stream.on("end", function() { // Finished streaming }); });
  • 55. Stream a file var gridStore = new GridStore(client, "test_gs_read_stream", "r"); gridStore.open(function(err, gs) { var stream = gs.stream(true); Receive a chunk and do something stream.on("data", function(chunk) { // Received a chunk of data }); Finshed stream the file stream.on("end", function() { // Finished streaming }); });
  • 56. Stream a file var gridStore = new GridStore(client, "test_gs_read_stream", "r"); gridStore.open(function(err, gs) { var stream = gs.stream(true); Receive a chunk and do something stream.on("data", function(chunk) { // Received a chunk of data }); Finshed stream the file stream.on("end", function() { // Finished streaming PR EFE RED }); });
  • 57. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}); } collection.count(function(err, count) { // count is > 0 <= 100 });
  • 58. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}); } All executed in parallel, non- deterministic end of execution collection.count(function(err, count) { // count is > 0 <= 100 });
  • 59. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}); } All executed in parallel, non- deterministic end of execution collection.count(function(err, count) { // count is > 0 <= 100 }); All inserts MAY have been written to disk so passes most of the time. But with Pooling NO WAY
  • 60. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, function(err, result) { // Do something }); } ?????????????????????????????? collection.count(function(err, count) { // count is > 0 <= 100 });
  • 61. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, function(err, result) { // Do something }); } How do we handle the callbacks ?????????????????????????????? collection.count(function(err, count) { // count is > 0 <= 100 });
  • 62. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, function(err, result) { // Do something }); } How do we handle the callbacks ?????????????????????????????? collection.count(function(err, count) { // count is > 0 <= 100 }); How do we get to this code ??????
  • 63. Typical starting problems for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, function(err, result) { // Do something }); } How do we handle the callbacks ?????????????????????????????? collection.count(function(err, count) { // count is > 0 <= 100 }); How do we get to this code ?????? Many possible solutions
  • 64. My Choosen Solution https://github.com/creationix/step Step( function insert() { var group = this.group(); for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, group()); } }, function finished() { collection.count(function(err, count) { // Count is 100 :) }); } )
  • 65. My Choosen Solution https://github.com/creationix/step Step( function insert() { var group = this.group(); for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, group()); } }, Ensures all the inserts are finished before calling the next function function finished() { collection.count(function(err, count) { // Count is 100 :) }); } )
  • 66. My Choosen Solution https://github.com/creationix/step Step( function insert() { var group = this.group(); for(var i = 0; i < 100; i++) { collection.insert({'i':i}, {safe:true}, group()); } }, Ensures all the inserts are finished before calling the next function function finished() { collection.count(function(err, count) { // Count is 100 :) }); } ) When all inserts are done :)
  • 67. DONE Code on https://github.com/christkv/mongodb-hamburg

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n