credit:https://medium.com/@joelrodrigues/how-to-access-mongodb-from-node-js-e37c587f226a
What is MongoDB?
MongoDB is a document database holding data in JSON format. Since it’s not based on joining, it’s easy to distribute data across servers by it’s sharding feature.
Developers can develop application which can be agnostic about deployments. MongoDB supports scaling out as opposed to RDBMS which supports scaling up. Mongo shell is written using C++ V8 for administering the MongoDB.
credit: http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/
_node.js_
is basically a_C++_
program that you control using_V8 javascript_
. So any applications you write using_node.js_
will be written in_javascript_
and it will control this_C++_
application (_node.js_
) and you’ll be able to say something like they made request for this resource and your application actually in_javascript_
will say: okey, they made a request for this resource, I don’t have to respond to that. Now respond accordingly.
Node.js
connects to MongoDB
using drivers. Installing 32
bit release shall be avoided because it limits the addressable size of data using the default storage engine.
To a layman, [JSON](http://json.org/)
is merely a string, anyways. JSON
objects are composed of key-value pairs. Keys must be strings, Keys and values must be separated by semi-colons. Fields within a JSON
object are separated by commas as delimiters. JSON
objects are opened and closed using curly braces:
{"string" : "sting value goes here","date" : "2015-10-27T22:35:21.908Z","number" : 123,"object" : {"key1" : "value1","key2" : "value2"},"boolean" : true,"array" : ["test",{ "key1" : "a", "key2" : "b" },[ "abc", "xyz" ]]}
The above example shows that JSON
supports a number of data-types. The object
field shows an example of nested values. As we can see object
and array
- MongoDB
data models commonly make use of nesting and even what we might call deep nesting. The flexibility JSON
provides makes it simple to implement different data access patterns by creating objects that contain all the data required to render a webpage full of content or say to provide another type of data view for users with very few requests.
MongoDB
stores data as [BSON](http://bsonspec.org/)
(binary JSON
). Here is the comparison:
// JSON{"hello": "world"}
// BSON"\x16\x00\x00\x00\x02hello\x00 \x06\ x00\ x00\ x00world\ x00\ x00 "
MongoDB
drivers send and recieve data in BSON
format and when the data is written to MongoDB
, it’s stored in BSON
.
On the application side, the drivers map BSON
to most appropriate native data types. It’s
MongoDB
documentsJSON
doesn’t distinguishes between integer
s and float
s. Doesn’t supports date
s. BSON
extends the JSON value types to include integer
s, double
s, date
s and binary data to support images and a number of other types of data.
To access the mongo
and mongod
directly from shell, Change the path for MongoDB:
System Properties
Advanced settings
Environment variables
System variables
Path
(this is where Windows looks for executables)MongoDB
’s startup location (eg: C:\Program Files\MongoDB\Server\3.2\bin
)Sometimes, you might need to refresh the system to see these shortcuts working
However before using mongodb
from terminal, create the C:\data\db
directory for MongoDB
to store data by following the below commands:
md \data\db
Notice, the \
before data\db
- this makes sure that the directory is created in root directory (in this case C:\
) only.
Now, if you type mongod
and hit Enter, it starts running. If you read the log printed on the terminal, it says that MongoDB
is listening on port=27017
and that dbpath=C:\data\db
i.e. the default path - which we created lately.
Now, once mongod
is running, we can start mongo
which makes a connection to port 27017
.
For the sake of testing this installation, we’ll do a simple document insert
using:
db.names.insert({name:'testing'})
and find
(or select
in relational terms) using the below command:
db.names.find()
Where {name:'testing'}
is an example of document. Also, to make the result of .find()
much readable, we can chain .pretty()
command.
We can run MongoDB
as a service as well.
In MongoDB
, documents are stored in colletions which are organized into databases. To see databases present in MongoDB
run show dbs
To insert a document into a collection, we first need to know how to specify that collection in the command. A collection and database that contains it form a namespace. When doing CRUD
operations, we reference the global variable db
. This variable holds the reference to the database we’re currently using. To switch to a database names test type MySQL like command use test
.
The insert operation returns a document as well, where acknowledged
set to true indicates that the record (or better say, document) was inserted successfully. All documents must have an underscore _id field. Each document in a collection must have a unique document id. At the heart of the query language for MongoDB
is a query by example strategy. We can pass a blank object {}
, key value pair {name: "Uber"}
. The result of find()
command is not a mere array of documents, it’s instead a cursor object
. We can see this:
var c = db.names.find();c.hasNext() //returns true, meaning there is a document yet to be visited by this cursorc.next() //grabs that document
To build applications using node.js, we first need to install it.
Let’s create a simple http
server:
// Source: howtonode.org/hello-node
// Load the http module to create an http server.var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests.var server = http.createServer(function (request, response) {response.writeHead(200, {"Content-Type": "text/plain"});response.end("Hello World\n");});
// Listen on port 8000, IP defaults to 127.0.0.1server.listen(8000);
// Put a friendly message on the terminalconsole.log("Server running at http://127.0.0.1:8000/");
Store the above code in a .js
file, let’s say app.js
And how do we start it?
In the terminal, go to the location of the file and type node app.js
. To verify, if it’s running or not, go to http://localhost:8000. Notice port 8000
, which we‘ve pecified in the above code.
var express = require('express'), cons = require('consolidate'), mongodb = require('mongodb');
require()
is how we add an external library in a node.js
application. If we run this code through node
terminal, we’ll get the below error:
To get this missing express
thing as a node
package, we can use node
command line npm install express
. In real projects, there will be a bunch of package dependencies. Installing them all one-by-one will be a big pain. To resolve this comes package.json
file. This file contains meta data about the dependencies:
{"name": "project name goes here","version": "0.1.2","description": "npm introduction","main": "app.js","dependencies": {"consolidate": "~0.13.1","express": "~4.13.3","mongodb": "~2.1.3"},"author": "ABC","license": "MIT"}
With this file in place, simply running npm install
will get all the packages for us inside project’s local node_modules
directory. There’s also a way to install packages globally.
The driver communicates with the MongoDB
server using it’s wire protocol. It handles things like opening sockets, detecting errors and managing connections to replica sets. To include the driver in an application, use code var mongodb = require('mongodb');
and install using npm install mongodb
. As we can see, it’s just a node package. Try to connect to MongoDB
using this package:
var MongoClient = require('mongodb').MongoClient,assert = require('assert');
var url = 'mongodb://localhost:27017/startup';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);console.log("Successfully connected to server");
// Find some documents in our collectiondb.collection('startup').find({}).toArray(function(err, docs) {
// Print the documents returneddocs.forEach(function(doc) {console.log(doc.name);});
// Close the DBdb.close();});
// Declare successconsole.log("Last call");});
In order to use the MongoDB Node.js driver
, it’s important to have a solid understanding of the asynchronous nature of IO
in javascript
, including database requests.
The
_mongo_
shell is synchronous meaning that when you issue a find command, it blocks waiting for command to return before continuing. This is not the case with_Node.js_
driver. Whether you’re doing a query, as we are here in the call defined or just setting up a connection to the database. As is common in_Javascript_
applications, the_Node.js_
driver we’re going to use is designed so that it’s methods function asynchronously. What this means is that instead of waiting on a return value from any methods we call, we instead pass in a callback function.
The second parameter in the above MongoClient.connect
call is a callback function. And is going to handle the result of this connection operation. Because of anysnchronous nature of node.js
, the following message gets printed before any database values:
_Last call_
Express
is a node.js
module that handles routing, request parameters and other details of HTTP
requests.
Here is a basic example of setting up a basic Express
server:
var express = require('express'),app = express();
app.get('/', function(req, res){res.send('Hello World');});
app.use(function(req, res){res.sendStatus(404);});
var server = app.listen(3000, function() {var port = server.address().port;console.log('Express server listening on port %s', port);});
The following example shows how to implement a HTML
template:
//file: app.jsvar express = require('express'), //set up the Express serverapp = express(), //use it to create an Express appengines = require('consolidate'); //use the wrapper library
app.engine('html', engines.nunjucks); //register nunjucks template engine
app.set('view engine', 'html'); //as being associated with the html extension, set the view engine app setting
app.set('views', __dirname + '/views'); //specify template location
app.get('/', function(req, res) {res.render('hello', { name : 'Templates' });});
app.use(function(req, res){res.sendStatus(404);});
var server = app.listen(3000, function() {var port = server.address().port;console.log('Express server listening on port %s', port);});
And the html
//file: views/hello.html
<h1>Hello, {{name}}!</h1>
In the above code, consolidate
is basically a set of wrappers for a number of template engines for Express
. Express
requires certain libraries to have a certain interface and consolidate
handles that for us. __dirname
is a node.js
variable which allows us to access to the directory in which the application file (in our case, app.js
) resides. Since, we’ve passed name : 'Templates'
- we’ll see the below output:
Here’s a more advanced version which connects to the database as well:
//file: app.js
var express = require('express'),app = express(),engines = require('consolidate'),MongoClient = require('mongodb').MongoClient,assert = require('assert');
app.engine('html', engines.nunjucks);app.set('view engine', 'html');app.set('views', __dirname + '/views');
MongoClient.connect('mongodb://localhost:27017/startup', function(err, db) {
assert.equal(null, err);console.log("Successfully connected to MongoDB.");
app.get('/', function(req, res){
db.collection('startup').find({}).toArray(function(err, docs) {res.render('startup', { 'name': docs } );});
});
app.use(function(req, res){res.sendStatus(404);});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log('Express server listening on port %s.', port);
});
});
and the html
//file: views/startup.html <h1>Hello, {{name}}!</h1>
var express = require('express'),app = express(),engines = require('consolidate');
app.engine('html', engines.nunjucks);app.set('view engine', 'html');app.set('views', __dirname + '/views');
// Handler for internal server errorsfunction errorHandler(err, req, res, next) {console.error(err.message);console.error(err.stack);res.status(500).render('error_template', { error: err });}
app.get('/:name', function(req, res, next) {var name = req.params.name;var getvar1 = req.query.getvar1;var getvar2 = req.query.getvar2;res.render('hello', { name : name, getvar1 : getvar1, getvar2 : getvar2 });});
app.use(errorHandler);
var server = app.listen(3000, function() {var port = server.address().port;console.log('Express server listening on port %s.', port);});
The hello
template is:
<h1>Hello, {{name}}, here are your GET variables:</h1><ul><li>{{getvar1}}</li><li>{{getvar2}}</li></ul>
and the error
template goes here:
<h1>Error: {{error}}</h1>
In the above app, we’re just registering only one route i.e. /:name
. The colon says to take this part of the URL and store in a variable called name
.
Will share further notes next week.
Originally published at xameeramir.github.io.