Difference between revisions of "MongoDB and NodeJs"

(NodeJs-Mongo)
(Docker Compose - MongoDb)
 
(18 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
=[[MongoDB]] =
 
=[[MongoDB]] =
 +
 +
==Docker Compose - MongoDb==
 +
docker-compose.yml
 +
<source>
 +
version: "2"
 +
services:
 +
  mongo:
 +
    image: mongo
 +
    ports:
 +
    - "27017:27017"
 +
</source>
 +
 +
To run the two dockers using the compose file execute the command:
 +
 +
<source>
 +
$ docker-compose up
 +
</source>
 +
 +
Lets test:
 +
<source>
 +
$ docker ps
 +
CONTAINER ID        IMAGE                        COMMAND...                 
 +
9a47337d30fe        easynodeauthentication_web  "npm start"...             
 +
c0f31757662b        mongo                        "docker..."...
 +
$ docker exec -it c0f31757662b /bin/bash
 +
$ mongo
 +
MongoDB shell version v3.4.10
 +
connecting to: mongodb://127.0.0.1:27017
 +
MongoDB server version: 3.4.10
 +
Welcome to the MongoDB shell.
 +
> show dbs
 +
admin    0.000GB
 +
local    0.000GB
 +
passport  0.000GB
 +
> use passport
 +
switched to db passport
 +
> show collections
 +
users
 +
> db.users.find({})
 +
{ "_id" : ObjectId("5a1f982615336e0010c38dd1"), "local" : { "password" : "$2a$08$rDBEIW7FBnH2LPk6E9ptFuv.J71/HrBZkQfdPjpiWDK/FUMHTto4y", "email" : "johndoe@example.com" }, "__v" : 0 }
 +
</source>
 +
 +
https://medium.com/@kahana.hagai/docker-compose-with-node-js-and-mongodb-dbdadab5ce0a
  
 
=[[NodeJs]]=
 
=[[NodeJs]]=
Line 24: Line 67:
 
>brew services start mongo #start/stop/status
 
>brew services start mongo #start/stop/status
 
</source>
 
</source>
 +
 +
'''From the Visual Studio Code Setup page:'''
 +
<source>
 +
 +
Tip: If you want to run VS Code from the terminal by simply typing 'code', VS Code has a command, Shell Command: Install 'code' command in PATH, to add 'code' to your $PATH variable list.
 +
 +
After installation, launch VS Code. '''Now open the Command Palette (F1 or ⇧+⌘+P on Mac) and type shell command to find the Shell Command: Install 'code' command in PATH command.'''
 +
 +
After executing the command, restart the terminal for the new $PATH value to take effect. You'll be able to simply type 'code .' in any folder to start editing files in that folder.
 +
</source>
 +
  
 
=NodeJs-Mongo=
 
=NodeJs-Mongo=
 +
==Create a project==
 
<source>
 
<source>
 
$ mkdir users => cd users
 
$ mkdir users => cd users
Line 55: Line 110:
  
  
 +
==package.json - project details and depencies file==
 +
'''package.json file:'''
 +
<syntaxhighlight lang="javascript">
 +
{
 +
  "name": "users",
 +
  "version": "1.0.0",
 +
  "description": "",
 +
  "main": "index.js",
 +
  "scripts": {
 +
    "test": "mocha"
 +
  },
 +
  "author": "",
 +
  "license": "ISC",
 +
  "dependencies": {
 +
    "mocha": "^5.2.0",
 +
    "mongoose": "^5.3.10",
 +
    "nodemon": "^1.18.6",
 +
    "request": "^2.88.0"
 +
  }
 +
}
 +
</syntaxhighlight>
  
 
==Mocha - Unit Test==
 
==Mocha - Unit Test==
 
Mocha is most famous test framework for javascript..
 
Mocha is most famous test framework for javascript..
  
 
+
===Creating data on MongoDb/Test===
 
'''test/create_test.js(test file):'''
 
'''test/create_test.js(test file):'''
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
Line 71: Line 147:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
'''package.json file:'''
+
'''test/create_test.js(another sample): '''
 +
<syntaxhighlight lang="javascript">
 +
const assert = require('assert');
 +
const User = require('../src/user');
 +
 
 +
 
 +
describe('Creating records',()=>{
 +
    it('saves a user',(done)=>{ //<------------ 1.callback
 +
        const joe = new User({ name: 'Joe'});
 +
       
 +
        //joe.save();
 +
        joe.save()
 +
        .then((result) => {
 +
            //Has joe been saved successfully?
 +
            assert(!joe.isNew);
 +
            done(); //<------------------- 2.callback: we should use
 +
        }).catch((err) => {
 +
            console.log('Error');
 +
        });
 +
 
 +
    });
 +
});
 +
</syntaxhighlight>
 +
 
 +
===Search/Find Record on Mongo===
 +
'''reading_test.js''':
 +
<syntaxhighlight lang="javascript">
 +
const assert = require('assert');
 +
const User = require('../src/user');
 +
 
 +
describe('Reading users out of the database', ()=>{
 +
    let joe;
 +
 
 +
    beforeEach((done)=>{
 +
        joe=new User({name:'Joe'});
 +
        joe.save()
 +
        .then((result) => {
 +
            done();
 +
        }).catch((err) => {
 +
            console.log('Error..');
 +
        });
 +
    });
 +
   
 +
    it('finds all users with a name of joe',(done)=>{
 +
        User.find({ name:'Joe' })
 +
          .then((users)=>{
 +
              console.log(users);
 +
              assert(users[0]._id.toString() === joe._id.toString());
 +
              done();
 +
          });
 +
    });
 +
 
 +
    it('find a user with a particular id', (done)=>{
 +
        User.findOne({_id:joe._id})
 +
        .then((user)=>{
 +
            assert(user.name === 'Joe');
 +
            done();
 +
        });
 +
    });
 +
});
 +
</syntaxhighlight>
 +
 
 +
===Deleting/removing records===
 +
 
 +
'''delete_test.js'''
 +
<syntaxhighlight lang="javascript">
 +
const assert = require('assert');
 +
const User = require('../src/user');
 +
 
 +
describe('Deleting a user',()=>{
 +
    let joe;
 +
 
 +
    beforeEach((done)=>{
 +
        joe = new User({name:'Joe'});
 +
        joe.save()
 +
        .then((result) => {
 +
            done();
 +
        }).catch((err) => {
 +
            console.log('delete:error in beforeEach!');
 +
        });
 +
    });
 +
 
 +
    it('model instance remove',(done)=>{
 +
        joe.remove()//it remove joe instance that we created in beforeEach method
 +
        .then(() => User.findOne({name:'Joe'}))//to test that the object deleted, it should return null
 +
        .then((user)=>{//then: they work sequentially
 +
            assert(user === null);
 +
            done();
 +
        })
 +
        ;
 +
    });
 +
 
 +
    it('class method remove',(done)=>{
 +
        //remove a bunch of records with some given criteria
 +
        User.remove({ name:'Joe' })
 +
        .then(()=>User.findOne({name:'Joe'}))
 +
        .then((user)=>{
 +
            assert(user === null);
 +
            done();
 +
        });
 +
    });
 +
 +
    it('class method findAndRemove',(done)=>{
 +
        User.findOneAndRemove({name:'Joe'})
 +
        .then(()=>User.findOne({name:'Joe'}))
 +
        .then((user)=>{
 +
            assert(user === null);
 +
            done();
 +
        });
 +
    });
 +
 
 +
    it('class method findByIdAndRemove',(done)=>{
 +
        User.findByIdAndRemove(joe._id)
 +
        .then(()=>User.findOne({name:'Joe'}))
 +
        .then((user)=>{
 +
            assert(user === null);
 +
            done();
 +
        });
 +
    });
 +
 
 +
 
 +
});
 +
</syntaxhighlight>
 +
 
 +
=== Updating records ===
 +
'''update_test.js''':
 +
<syntaxhighlight lang="javascript">
 +
const assert=require('assert');
 +
const User = require('../src/user');
 +
 
 +
describe('Updating records',()=>{
 +
    let joe;
 +
 
 +
    beforeEach((done)=>{
 +
        joe = new User({name:'Joe'});
 +
        joe.save()
 +
        .then(()=>done());
 +
    });
 +
 
 +
    function assertName(operation, done){
 +
        operation
 +
            .then(()=>User.find({}))
 +
            .then((users)=>{
 +
                assert(users.length === 1);
 +
                assert(users[0].name === 'Alex');
 +
                done();
 +
            });
 +
    }
 +
 
 +
    //set and save: when you update more record(emaıl, phone, address),
 +
    //like a transactional update,
 +
    //we can update all data, and then save all.
 +
    it('instance type using set n save',(done)=>{
 +
      console.log(joe);
 +
      joe.set('name','Alex');
 +
      assertName(joe.save(),done);
 +
      console.log(joe);
 +
    });
 +
 
 +
    //update : directly update
 +
    it('A model instance can update',(done)=>{
 +
        assertName(joe.update({name:'Alex'}),done);
 +
    }); 
 +
 
 +
    it('A model class can update', (done)=>{
 +
        assertName(
 +
            User.update({name:'Joe',name:'Alex'}),
 +
            done
 +
        );
 +
    });
 +
 
 +
    it('A model class can update one record', (done)=>{
 +
        assertName(
 +
            User.findOneAndUpdate({name:'Joe',name:'Alex'}),
 +
            done
 +
        );
 +
    });
 +
 
 +
    it('A model class can find a record with an Id and update',(done)=>{
 +
        assertName(
 +
            User.findByIdAndUpdate(joe._id,{name:'Alex'}),
 +
            done
 +
        );
 +
    });
 +
 
 +
});
 +
</syntaxhighlight>
 +
 
 +
=== Run the test : npm run test===
 +
<source>
 +
$ npm run test
 +
</source>
 +
 
 +
==Automating Test==
 +
    "test": "nodemon --exec 'mocha -R min'" : formats and clear the output
 +
If I change the code, it runs test again for changes.
 +
 
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
{
 
{
Line 79: Line 351:
 
   "main": "index.js",
 
   "main": "index.js",
 
   "scripts": {
 
   "scripts": {
     "test": "mocha"
+
     "test": "nodemon --exec 'mocha -R min'"
 
   },
 
   },
 
   "author": "",
 
   "author": "",
Line 90: Line 362:
 
   }
 
   }
 
}
 
}
 +
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
=MongoDB with Node and Express=
 +
'''Node''':Engine for running JavaScript outside of a browser environment. Can work with HTTP requests.
 +
 +
'''Express''':Framework to simplify working with HTTP requests.
  
 +
http://rasimsen.com/images/node-express-mongo-rest-api.png
 +
 +
 +
==Create a new project==
 
<source>
 
<source>
$ npm run test
+
$ mkdir muber
 +
$ cd muber
 +
$ npm init
 +
$ code . #to open in a editor(atom, code)
 
</source>
 
</source>
  
 +
to install some dependencies..
 +
you can use '''SuperTest''' which is can be used to test HTTP endpoints.
 +
<source>
 +
$ sudo npm install --save nodemon mongoose express mocha
 +
$ sudo npm install --save supertest #you can use SuperTest which is can be used to test HTTP endpoints.
 +
$ sudo npm install --save body-parser #Parse incoming request bodies in a middleware before your handlers, available under the req.body property.
 +
</source>
  
 +
==Environment Definition==
  
<syntaxhighlight lang="javascript">
+
node-express-mongo-environment-variable.png
 
 
</syntaxhighlight>
 
  
<syntaxhighlight lang="javascript">
 
 
</syntaxhighlight>
 
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">

Latest revision as of 16:38, 5 July 2019

MongoDB

Docker Compose - MongoDb

docker-compose.yml

version: "2"
services:
  mongo:
    image: mongo
    ports:
    - "27017:27017"

To run the two dockers using the compose file execute the command:

$ docker-compose up

Lets test:

$ docker ps
CONTAINER ID        IMAGE                        COMMAND...                  
9a47337d30fe        easynodeauthentication_web   "npm start"...              
c0f31757662b        mongo                        "docker..."...
$ docker exec -it c0f31757662b /bin/bash
$ mongo
MongoDB shell version v3.4.10
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.10
Welcome to the MongoDB shell.
> show dbs
admin     0.000GB
local     0.000GB
passport  0.000GB
> use passport
switched to db passport
> show collections
users
> db.users.find({})
{ "_id" : ObjectId("5a1f982615336e0010c38dd1"), "local" : { "password" : "$2a$08$rDBEIW7FBnH2LPk6E9ptFuv.J71/HrBZkQfdPjpiWDK/FUMHTto4y", "email" : "johndoe@example.com" }, "__v" : 0 }

https://medium.com/@kahana.hagai/docker-compose-with-node-js-and-mongodb-dbdadab5ce0a

NodeJs

Installation

We will install :

  • MongoDb
  • Node
  • Robomongo - editor

brew - package manager can be used on MacOs

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

https://brew.sh/

Mongo Installation:

>brew install mongo
>mongod
>sudo mkdir -p /data/db
>sudo chown -Rv rasimsen /data/db
>brew services start mongo #start/stop/status

From the Visual Studio Code Setup page:

Tip: If you want to run VS Code from the terminal by simply typing 'code', VS Code has a command, Shell Command: Install 'code' command in PATH, to add 'code' to your $PATH variable list.

After installation, launch VS Code. '''Now open the Command Palette (F1 or ⇧+⌘+P on Mac) and type shell command to find the Shell Command: Install 'code' command in PATH command.'''

After executing the command, restart the terminal for the new $PATH value to take effect. You'll be able to simply type 'code .' in any folder to start editing files in that folder.


NodeJs-Mongo

Create a project

$ mkdir users => cd users
$ mkdir src
$ mkdir test
$ npm install request --save #url için
$ npm install --save mocha nodemon mongoose

mocha: unit test nodemon: mongoose : mongo db driver

src/user.js:

const mongoose=require('mongoose');
const Schema=mongoose.Schema;

const UserSchema = new Schema({
    name:String
});

const User = mongoose.model('User',UserSchema);

module.exports = User;


package.json - project details and depencies file

package.json file:

{
  "name": "users",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mocha": "^5.2.0",
    "mongoose": "^5.3.10",
    "nodemon": "^1.18.6",
    "request": "^2.88.0"
  }
}

Mocha - Unit Test

Mocha is most famous test framework for javascript..

Creating data on MongoDb/Test

test/create_test.js(test file):

const assert = require('assert');

describe('Creating records',()=>{
    it('saves a user',()=>{
        assert(1+1 ===2);
    });
});

test/create_test.js(another sample):

const assert = require('assert');
const User = require('../src/user');


describe('Creating records',()=>{
    it('saves a user',(done)=>{ //<------------ 1.callback 
        const joe = new User({ name: 'Joe'});
        
        //joe.save();
        joe.save()
        .then((result) => {
            //Has joe been saved successfully?
            assert(!joe.isNew);
            done(); //<------------------- 2.callback: we should use 
        }).catch((err) => {
            console.log('Error');
        });

    });
});

Search/Find Record on Mongo

reading_test.js:

const assert = require('assert');
const User = require('../src/user');

describe('Reading users out of the database', ()=>{
    let joe;

    beforeEach((done)=>{
        joe=new User({name:'Joe'});
        joe.save()
        .then((result) => {
            done(); 
        }).catch((err) => {
            console.log('Error..');
        });
    });
    
    it('finds all users with a name of joe',(done)=>{
        User.find({ name:'Joe' })
           .then((users)=>{
               console.log(users);
               assert(users[0]._id.toString() === joe._id.toString());
               done();
           });
    });

    it('find a user with a particular id', (done)=>{
        User.findOne({_id:joe._id})
        .then((user)=>{
            assert(user.name === 'Joe');
            done();
        });
    });
});

Deleting/removing records

delete_test.js

const assert = require('assert');
const User = require('../src/user');

describe('Deleting a user',()=>{
    let joe;

    beforeEach((done)=>{
        joe = new User({name:'Joe'});
        joe.save()
        .then((result) => {
            done();
        }).catch((err) => {
            console.log('delete:error in beforeEach!');
        });
    });

    it('model instance remove',(done)=>{
        joe.remove()//it remove joe instance that we created in beforeEach method
        .then(() => User.findOne({name:'Joe'}))//to test that the object deleted, it should return null
        .then((user)=>{//then: they work sequentially
            assert(user === null);
            done();
        })
        ;
    });

    it('class method remove',(done)=>{
        //remove a bunch of records with some given criteria
        User.remove({ name:'Joe' })
        .then(()=>User.findOne({name:'Joe'}))
        .then((user)=>{
            assert(user === null);
            done();
        });
    });
 
    it('class method findAndRemove',(done)=>{
        User.findOneAndRemove({name:'Joe'})
        .then(()=>User.findOne({name:'Joe'}))
        .then((user)=>{
            assert(user === null);
            done();
        });
    });

    it('class method findByIdAndRemove',(done)=>{
        User.findByIdAndRemove(joe._id)
        .then(()=>User.findOne({name:'Joe'}))
        .then((user)=>{
            assert(user === null);
            done();
        });
    });


});

Updating records

update_test.js:

const assert=require('assert');
const User = require('../src/user');

describe('Updating records',()=>{
    let joe;

    beforeEach((done)=>{
        joe = new User({name:'Joe'});
        joe.save()
        .then(()=>done());
    });

    function assertName(operation, done){
        operation
            .then(()=>User.find({}))
            .then((users)=>{
                assert(users.length === 1);
                assert(users[0].name === 'Alex');
                done();
            });
    }

    //set and save: when you update more record(emaıl, phone, address), 
    //like a transactional update,
    //we can update all data, and then save all.
    it('instance type using set n save',(done)=>{
       console.log(joe);
       joe.set('name','Alex');
       assertName(joe.save(),done);
       console.log(joe); 
    });

    //update : directly update
    it('A model instance can update',(done)=>{
        assertName(joe.update({name:'Alex'}),done);
    });  

    it('A model class can update', (done)=>{
        assertName(
            User.update({name:'Joe',name:'Alex'}),
            done
        );
    });

    it('A model class can update one record', (done)=>{
        assertName(
            User.findOneAndUpdate({name:'Joe',name:'Alex'}),
            done
        );
    });

    it('A model class can find a record with an Id and update',(done)=>{
        assertName(
            User.findByIdAndUpdate(joe._id,{name:'Alex'}),
            done
        );
    });

});

Run the test : npm run test

$ npm run test

Automating Test

   "test": "nodemon --exec 'mocha -R min'" : formats and clear the output

If I change the code, it runs test again for changes.

{
  "name": "users",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "nodemon --exec 'mocha -R min'"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mocha": "^5.2.0",
    "mongoose": "^5.3.10",
    "nodemon": "^1.18.6",
    "request": "^2.88.0"
  }
}

MongoDB with Node and Express

Node:Engine for running JavaScript outside of a browser environment. Can work with HTTP requests.

Express:Framework to simplify working with HTTP requests.

node-express-mongo-rest-api.png


Create a new project

$ mkdir muber
$ cd muber
$ npm init
$ code . #to open in a editor(atom, code)

to install some dependencies.. you can use SuperTest which is can be used to test HTTP endpoints.

$ sudo npm install --save nodemon mongoose express mocha
$ sudo npm install --save supertest #you can use SuperTest which is can be used to test HTTP endpoints.
$ sudo npm install --save body-parser #Parse incoming request bodies in a middleware before your handlers, available under the req.body property.

Environment Definition

node-express-mongo-environment-variable.png


Errors

(node:27919) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.

Solution: Check your mongo version

mongo --version
If you are using version >= 3.1.0 change you mongo connection file to ->

MongoClient.connect("mongodb://localhost:27017/YourDB", { useNewUrlParser: true })
or your mongoose connection file to ->

mongoose.connect("mongodb://localhost:27017/YourDB", { useNewUrlParser: true });
Ideally, it's a version 4 feature but v3.1.0 and above is supporting it too. Check out MongoDB Github for details.

Error: TypeError: User is not a constructor Solution: Node is a case-sensetive language. Check your model or object..