- A database is an organized collection of data
- This data can be organized by any criteria
- Using a database we can read, create, update and delete data
- Now a day we can find different types of databases that fulfill different projects needs
- We can split the big database family into two big categories: Relational or No relational or NoSQL
- The Relational are known as SQL databases (as they use SQL as query language)
- NoSQL databases are No relational
- Each database type will have pros and cons when reading, creating, updating or deleting values
- We need to choose the right database for our job and know why we're going to use it
- In this course section we'll learn MongoDB that's a NoSQL database
- What is a Relational Database?
- Khan Academy - Intro to SQL: Querying and managing data
- SQL for Beginners. Learn basics of SQL in 1 Hour
- W3 Schools
- NoSQL (Not Only SQL) is the given name for databases that are not relationals
- In this database family we can find different types of databases like
key/value, document oriented, grapsh or big tables - All this databases are prepare to horizontaly scale (this means that we can add more databases servers if we need so)
- In some cases we can even use a simple computer (not much hardware) to solve a business problem
- Martin Fowler gave a great Introduction to NoSQL talk where he explains all this concepts
- This talk is a must to understand this subject
- Also, you can read on his blog about it
- MongoDB is a NoSQL document oriented database
- This database a;low us to store data in JSON format
- It has a flexible schema, this means that we can change/update our documents structure whenever we need it
- This becomes helpful as we develop and we don't have the final data structure
- MongoDB also it's prepared to horizontal scale in a easy way
- As we learned JavaScript we'll use a database engine that allows us to keep on using this language to store our data
- To use MongoDB locally we need to download & install it
- Open the documentation to Install MongoDB Community Edition and choose your OS MongoDB version
- Windows
- For Windows, execute the downloaded installer, follow all the default wizard steps and MongoDB will be installed on the following path
C:\Program Files\MongoDB\Server\3.4\. - To be able to access MongoDB from anywhere in the terminal we need to configure our environments variables
- For Windows, execute the downloaded installer, follow all the default wizard steps and MongoDB will be installed on the following path
- Mac
- For Mac, use Homebrew to install MongoDB
- Linux
- Windows
-
After adding MongoDB to our path we can start a server instance
- Windows:
mongod.exe
- Linux/Mac:
mongod
- Windows:
-
Once MongoDB starts will show us server configuration information
-
It will show the configured database
/data/db -
Engine type
wiredTiger -
Default MongoDB port
27017[initandlisten] Detected data files in /data/db created by the 'wiredTiger' storage engine, so setting the active storage engine to 'wiredTiger' I NETWORK [thread1] waiting for connections on port 27017
-
To interact with MongoDB we need the server runnig (mongod) and a MongoDB shell
-
Start MongoDB shell running the following command:
- Windows:
mongo.exe
- Linux/Mac:
mongo
- Windows:
-
Once MongoDB shell connects we'll see a description message:
MongoDB shell version v3.4.2 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.2 > -
MongoDB shell let us know that it's connected to
mongodb://127.0.0.1:27017 -
Also shows the shell and server version (
v3.4.2) -
To use MongoDB we need the server and shell running
-
MongoDB shell it's a JavaScript REPL like Node.js one
-
This means that we can write/execute JavaScript code on it
> 2 + 2 4 -
To start learning mongo shell we can execute the
helpcommand that will show all the commands that we can use> help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell
-
One of the commands it's
show dbs -
This command will let show us all the local databases
> show dbs local 0.000GB test 0.000GB
-
To know which database we're using we can call
db -
dbit's just a JavaScript variable that has the selected database -
By default MongoDB will set the initial selected database to
test> db test >
-
MongoDB has databases
-
MongoDB Databases has collections
-
A collection is where we can store our documents grouped by some criteria
-
This means that by using the database and the collection we'll have a namespace
database.collection
-
For example we can have a
comicsdatabase with asuperheroescollection -
To access the
superheroescollection we need to callcomics.superheroes
-
To create a new datbase we use the
use dabasenamecommand -
In this case we run
use comics switched to db comics
-
The
usecommand will create a new database if it doesn't exists or swith to the selected one -
MongoDB will create our databases and collections in a
lazzyway -
This means that it won't really, really create it until it has some data on it
-
We can still use the databases and collection while we don't have data on it but it's not persisted
-
When we change databases MongoDB will change the
dbreferenceswitched to db comics -
If we type db we can see the selected database
> db comics
-
To create a new document we use the
insertOnecommand -
This method accepts a JSON object as parameter
-
This JSON object represents the document that we want to store in our database collection
-
Use
dbto let MongoDB in which database we would like to store this document -
This means that we need to be sure that we
usethe right database first> use comics switched to db comics > db.superheroes.insertOne({ "name": "SPIDER-MAN", "image": "spiderman.jpg" }) { "acknowledged" : true, "insertedId" : ObjectId("5b055c94f9ca342c9eaaf73e") }
-
Once we inserted a document MongoDB will show us a result message
-
"acknowledged" : truemeans that it was able to store the document -
"insertedId" : ObjectId("59c6eae6eb2fe8bf77e9c391")MongoDB creates a new ID for each new document -
Our document has a
_idproperty with thisinsertedIdvalue -
ObjectIdis a data type supported by MongoDB to manage documents ids -
We can insert some other documents
> db.superheroes.insertOne({ "name": "CAPTAIN MARVEL", "image": "captainmarvel.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf73f") } > db.superheroes.insertOne({ "name": "HULK", "image": "hulk.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf740") } > db.superheroes.insertOne({ "name": "THOR", "image": "thor.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf741") } > db.superheroes.insertOne({ "name": "IRON MAN", "image": "ironman.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf742") } > db.superheroes.insertOne({ "name": "DAREDEVIL", "image": "daredevil.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf743") } > db.superheroes.insertOne({ "name": "BLACK WIDOW", "image": "blackwidow.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf744") } > db.superheroes.insertOne({ "name": "CAPTAIN AMERICA", "image": "captanamerica.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f19f9ca342c9eaaf745") } > db.superheroes.insertOne({ "name": "WOLVERINE", "image": "wolverine.jpg" }); { "acknowledged" : true, "insertedId" : ObjectId("5b055f1bf9ca342c9eaaf746") }
-
Now MongoDB stored our database and collection
-
So we can use the
comics.superheroescollection -
Use
show collectionsto know the database collections> show collections superheroes -
Also, we can check that the database has been saved too using
show dbs> show dbs comics -
Once we have a database created we can start MongoDB shell and specify the initial selected database
-
The
mongocommand accepts the initial selected database as parametermongo comics > db comics -
Full example:
mongo comics MongoDB shell version v3.4.2 connecting to: mongodb://127.0.0.1:27017/comics MongoDB server version: 3.4.2 Server has startup warnings: 2018-05-23T07:07:16.271-0500 I CONTROL [initandlisten] 2018-05-23T07:07:16.271-0500 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-05-23T07:07:16.271-0500 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-05-23T07:07:16.271-0500 I CONTROL [initandlisten] > db comics
-
Use
findto show the collection documents -
If we don't pass any parameter to the find method it will return all the collection documents
> db.superheroes.find() { "_id" : ObjectId("5b055c94f9ca342c9eaaf73e"), "name" : "SPIDER-MAN", "image" : "spiderman.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf73f"), "name" : "CAPTAIN MARVEL", "image" : "captainmarvel.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf740"), "name" : "HULK", "image" : "hulk.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf741"), "name" : "THOR", "image" : "thor.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf742"), "name" : "IRON MAN", "image" : "ironman.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf743"), "name" : "DAREDEVIL", "image" : "daredevil.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf744"), "name" : "BLACK WIDOW", "image" : "blackwidow.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf745"), "name" : "CAPTAIN AMERICA", "image" : "captanamerica.jpg" } { "_id" : ObjectId("5b055f1bf9ca342c9eaaf746"), "name" : "WOLVERINE", "image" : "wolverine.jpg" }
-
In this case we have 9 inserted documents
-
Each of them have an unique
_idproperty to identify it -
All documents have a name property too
-
The
findmethod accepts an object with properties criteria to query documents -
It will bring all documents if we pass an empty object as we're not using any criteria
> db.superheroes.find({}) { "_id" : ObjectId("5b055c94f9ca342c9eaaf73e"), "name" : "SPIDER-MAN", "image" : "spiderman.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf73f"), "name" : "CAPTAIN MARVEL", "image" : "captainmarvel.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf740"), "name" : "HULK", "image" : "hulk.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf741"), "name" : "THOR", "image" : "thor.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf742"), "name" : "IRON MAN", "image" : "ironman.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf743"), "name" : "DAREDEVIL", "image" : "daredevil.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf744"), "name" : "BLACK WIDOW", "image" : "blackwidow.jpg" } { "_id" : ObjectId("5b055f19f9ca342c9eaaf745"), "name" : "CAPTAIN AMERICA", "image" : "captanamerica.jpg" } { "_id" : ObjectId("5b055f1bf9ca342c9eaaf746"), "name" : "WOLVERINE", "image" : "wolverine.jpg" }
-
We can also add a criteria to search by
-
For example we can query documents by name
> db.superheroes.find({ "name": "WOLVERINE" }) { "_id" : ObjectId("5b055f1bf9ca342c9eaaf746"), "name" : "WOLVERINE", "image" : "wolverine.jpg" }
-
In this case we only have one document with WOLVERINE as name
-
We can use any document property to query by
> db.superheroes.find({ "image": "captanamerica.jpg" }) { "_id" : ObjectId("5b055f19f9ca342c9eaaf745"), "name" : "CAPTAIN AMERICA", "image" : "captanamerica.jpg" }
-
It looks like
findreturns documents -
But in reality it returns a
cursor -
As we have JavaScript we can assign the find returned value to a variable
-
Dado que no le pasamos parámetro esta búsqueda retorna todos los documentos que tenemos en la colección
-
Using limit we can
limitthe amount of documents that we query -
In this example we'll get the first three collection documents
> const cursor = db.superheroes.find().limit(3)
-
We can know if we can iterate over the cursor using
hasNext() -
This method will return a boolean value
-
In case it's true then we can call the next value
> cursor.hasNext() true
-
Al ser un cursor el restulado podemos llamar al método
nextpara obtener el próximo resultado> cursor.next() { "_id" : ObjectId("5b055c94f9ca342c9eaaf73e"), "name" : "SPIDER-MAN", "image" : "spiderman.jpg" } > cursor.next() { "_id" : ObjectId("5b055f19f9ca342c9eaaf73f"), "name" : "CAPTAIN MARVEL", "image" : "captainmarvel.jpg" } > cursor.next() { "_id" : ObjectId("5b055f19f9ca342c9eaaf740"), "name" : "HULK", "image" : "hulk.jpg" }
-
In case we can call
nextthree times as it's the result we got from the find calls -
Once we reach the last document hasNext() will return false and we know we can't iterate
-
MongoDB will show an error if we try to iterate more documents that the cursor has
> cursor.hasNext() false > cursor.next() E QUERY [thread1] Error: error hasNext: false : DBQuery.prototype.next@src/mongo/shell/query.js:305:1 @(shell):1:1
-
To delete a collection we use the collection
dropmethod> db.superheroes.drop() true > show collections >
-
Calling collection
dropmethod will delete all the collection documents
-
We can also drop a database using the database
dropDatabasemethodshow dbs local 0.000GB test 0.000GB comics 0.000GB > use comics > db.dropDatabase() { "dropped" : "comics", "ok" : 1 } > show dbs local 0.000GB test 0.000GB
-
Calling
db.dropDatabase()we tell MongoDB to delete the selecteddbdatabase -
Once we dropped the database we can recreate using
use> use comics switched to db comics
-
To insert a document we use the collection method
insertOne -
To insert many documents we use the collection method
insertMany -
insertManyaccpets a document collection as parameter in JSON format> db.superheroes.insertMany([ { "name": "SPIDER-MAN", "image": "spiderman.jpg" }, { "name": "CAPTAIN MARVEL", "image": "captainmarvel.jpg" }, { "name": "HULK", "image": "hulk.jpg" }, { "name": "THOR", "image": "thor.jpg" }, { "name": "IRON MAN", "image": "ironman.jpg" }, { "name": "DAREDEVIL", "image": "daredevil.jpg" }, { "name": "BLACK WIDOW", "image": "blackwidow.jpg" }, { "name": "CAPTAIN AMERICA", "image": "captanamerica.jpg" }, { "name": "WOLVERINE", "image": "wolverine.jpg" } ]) { "acknowledged" : true, "insertedIds" : [ ObjectId("5b0569b32c95847cf4135e75"), ObjectId("5b0569b32c95847cf4135e76"), ObjectId("5b0569b32c95847cf4135e77"), ObjectId("5b0569b32c95847cf4135e78"), ObjectId("5b0569b32c95847cf4135e79"), ObjectId("5b0569b32c95847cf4135e7a"), ObjectId("5b0569b32c95847cf4135e7b"), ObjectId("5b0569b32c95847cf4135e7c"), ObjectId("5b0569b32c95847cf4135e7d") ] }
-
Now we can call
findagain to retrieve all documents> db.superheroes.find() { "_id" : ObjectId("5b0569b32c95847cf4135e75"), "name" : "SPIDER-MAN", "image" : "spiderman.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e76"), "name" : "CAPTAIN MARVEL", "image" : "captainmarvel.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e77"), "name" : "HULK", "image" : "hulk.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e78"), "name" : "THOR", "image" : "thor.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e79"), "name" : "IRON MAN", "image" : "ironman.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7a"), "name" : "DAREDEVIL", "image" : "daredevil.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7b"), "name" : "BLACK WIDOW", "image" : "blackwidow.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7c"), "name" : "CAPTAIN AMERICA", "image" : "captanamerica.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7d"), "name" : "WOLVERINE", "image" : "wolverine.jpg" }
-
In this example we see how to drop and insert many new documents
-
insertManyworks in a similar way asinsertOnebut with a collection of documents -
We get all the inserted documents ids
-
Also we can count the collections document using the collection method
count> db.superheroes.find().count() 9
- Sometimes our documents are too big and it's difficult to read
- That's why MongoDB has a
prettypmethod to show documents result better> db.superheroes.find().pretty() { "_id" : ObjectId("5b0569b32c95847cf4135e75"), "name" : "SPIDER-MAN", "image" : "spiderman.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e76"), "name" : "CAPTAIN MARVEL", "image" : "captainmarvel.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e77"), "name" : "HULK", "image" : "hulk.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e78"), "name" : "THOR", "image" : "thor.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e79"), "name" : "IRON MAN", "image" : "ironman.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7a"), "name" : "DAREDEVIL", "image" : "daredevil.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7b"), "name" : "BLACK WIDOW", "image" : "blackwidow.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7c"), "name" : "CAPTAIN AMERICA", "image" : "captanamerica.jpg" } { "_id" : ObjectId("5b0569b32c95847cf4135e7d"), "name" : "WOLVERINE", "image" : "wolverine.jpg" }
-
We can also search documents for more than one criteria
> db.superheroes.find({"name": "WOLVERINE", "image" : "wolverine.jpg"}) { "_id" : ObjectId("5b0569b32c95847cf4135e7d"), "name" : "WOLVERINE", "image" : "wolverine.jpg" }
-
In this case we're searching for a document with the WOLVERINE name and wolverine.jpg as image
-
If we search using other parameters we might not get documents back
> db.superheroes.find({"name": "WOLVERINE", "image" : "captanamerica.jpg"})
-
MongoDB is not able to retrieve any documents as we don't have any document with name WOLVERINE and image captanamerica.jpg
-
To update a document we use the collection method
updateOne -
This method accepts an object as first parameter with the
findcriteria -
The second parameter is an object with a special operator called
$set -
$setuses an object with the document property that we want to update and the corresponding value> db.superheroes.updateOne({ "name": "WOLVERINE"}, { $set: { "name": "LOGAN"}}) { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 } { "_id" : ObjectId("5b0569b32c95847cf4135e7d"), "name" : "LOGAN", "image" : "wolverine.jpg" }
-
MongoDB updates the document and inform the operation status showing the amount of updated documents that match the critearia
-
As MongoDB doesn't have a rigid schema we can add any property to any document without changing the rest of the documents
-
For example we could add a power property to the hulk document
> db.superheroes.updateOne({ "name": "HULK"}, { $set: { "power": 100}}) { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
-
Now we can query the Hulk document
> db.superheroes.find({"name": "HULK"}).pretty() { "_id" : ObjectId("5b0569b32c95847cf4135e77"), "name" : "HULK", "image" : "hulk.jpg", "power" : 100 }
-
Now we can see that power was added to the document with Hulk name
> b.superheroes.find().limit(1).pretty() { "_id" : ObjectId("5b0569b32c95847cf4135e75"), "name" : "SPIDER-MAN", "image" : "spiderman.jpg" }
-
We still see that the rest of the document haven't been updated with the new property
-
In this examples we have been using the name property to find our documents
-
What could it happen if we have more than one document with the same name?
-
The only way to make sure that we're going to update the right document is using the document id
-
Remember that the documents hava a
_idproperty by default and this value is created by MongoDB to be unique -
To update a document using the id we do it using
ObjectId(id)> db.superheroes.updateOne({"_id": ObjectId("5b0569b32c95847cf4135e77")}, { $set: { "name": "THE HULK"}}) { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
-
We can also search by id
> db.superheroes.find({ "_id": ObjectId("5b0569b32c95847cf4135e77")}).pretty() { "_id" : ObjectId("5b0569b32c95847cf4135e77"), "name" : "THE HULK", "image" : "hulk.jpg", "power" : 100 }
-
Excelent now we can use
_idin our queries
-
To delete a document we use
deleteOne -
This method will delete the first document that match the query criteria
-
To be sure that we don't delete the wrong document we can use
_idtoo> db.superheroes.deleteOne({ "_id": ObjectId("5b0569b32c95847cf4135e77")}) { "acknowledged" : true, "deletedCount" : 1 } > db.superheroes.find({ "_id": ObjectId("5b0569b32c95847cf4135e77")}) >
-
Using
deleteOneandObjectId()we can delete a document -
We could use any criteria (example: name property) to delete a document by
-
In case we need to delete many documents with the same criteria we can use the collection method
deleteMany> db.superheroes.deleteMany({}) { "acknowledged" : true, "deletedCount" : 8 }
-
As we passed an empty array we delete all the collections documents
-
To use MongoDB from Node.js we need to use the MongoDB official driver
npm i mongodb
-
Once we installed Mongo we need to require MongoClient from this module
const MongoClient = require('mongodb').MongoClient;
-
Also we need to set up MongoDB url to connect with
const url = 'mongodb://localhost:27017';
-
We know that by default MongoDB uses port 27017 and we have it installed in our local environment
-
MongoClienthas aconnectmethod that allows us to connect to MongoDB using Node.j -
This method accepts the MongoDB server
address (url)and acallback function -
The callback function gets two parameters:
- The first parameter is an
errorobject - The second parameter ir a
clientobject
MongoClient.connect(url, function(err, client) { console.log("Connected successfully to server"); });
- The first parameter is an
-
We're going to use the client object to get the database
-
The client object has a
dbmethod that accepts a string with the database name -
It returns a database object
const db = client.db('comics');
-
The same as using MongoDB shell we need to use a collection
-
The
dbobject that we got from theclientone has acollectionmethod that allow us to select the collection -
This method accepts a string with the collection name
-
This method returns a collection object
const collection = db.collection('superheroes');
-
Now that we have the collection we can use the
findmethod to query -
The
findmethod accepts an object with the criteria to search bycollection.find({})
-
The
findmethod returns acursorobject -
We need to find a way to transform our cursor into objects to use the documents we get back
-
That's why the cursor object has a
toArraymethod that will transform the result into an array of objects (documents) -
The toArray object accepts a callback
-
This callback gets two parameters, first an error and second the documents that it get back
collection.find({}).toArray((error, documents) => { console.log(documents); })
-
As we opened a connection to the MongoDB we need to close it if we're not using it
-
The
clientobject has aclosemethod that will close the database connectionclient.close();
-
Great now we know how the mongodb driver works
-
Lets put everything together
const MongoClient = require('mongodb').MongoClient; const url = 'mongodb://localhost:27017'; MongoClient.connect(url, function(err, client) { const db = client.db('comics'); const collection = db.collection('superheroes'); collection.find({}).toArray((error, documents) => { console.log(documents); client.close(); }); });
-
Using express we'll need to add this code to our route handler
app.get('/', (req, res) => { MongoClient.connect(url, function(err, client) { const db = client.db('comics'); const collection = db.collection('superheroes'); collection.find({}).toArray((error, documents) => { client.close(); res.render('index', { documents: documents }); }); }); });
-
Close the connection before sending the response to the client
-
Now we know how to query MongoDB from Node.js and also using Express route
-
But what about inserting, updating or deleting documents?
-
The MongoDB driver has methods for each case
-
Check the MongoDB driver collection methods doc
-
As you can see there're a lot of things that we can do once we have a collection
-
To insert documents we have two methods:
insertOne & insertManyconst doc = { "name": "CAPTAIN MARVEL", "image": "captainmarvel.jpg" }; collection.insertOne(doc, (err, result) => { callback(result); });
-
Now insert many documents using an array
const documents = [ { "name": "CAPTAIN MARVEL", "image": "captainmarvel.jpg" }, { "name": "HULK", "image": "hulk.jpg" }, { "name": "THOR", "image": "thor.jpg" } ]; collection.insertMany(documents, (err, result) => { callback(result); });
-
Update also has two methods:
updateOne & updateMany -
This updates methods accepts a filter object as first parameter
-
Also accepts a second parameter that's a callback
const filter = { name: 'HULK' }; const update = { $set: { power: 100 } }; collection.updateOne(filter, update, (err, result) => { callback(result); });
-
We can do the same with updateMany
const filter = { name: 'HULK' }; const update = { $set: { power: 100 } }; collection.updateMany(doc, update, (err, result) => { callback(result); });
-
If we have more than one document with the name HULK it will update the power to 100
-
Finally we can delete documents using MongoDB driver two methods:
deleteOne & deleteMany -
As we're going to delete documents now it's a good time about MongoDB ObjectID
-
MongoDB driver has a
const ObjectID = require('mongodb').ObjectID; const filter = { _id: ObjectID('5b07560bda15952ac0b33e6c')}; collection.deleteOne(query, function(err, result) { callback(result); });
- Express apps can use any database supported by Node (Express itself doesn't define any specific additional behavior/requirements for database management). There are many popular options, including PostgreSQL, MySQL, Redis, SQLite, and MongoDB.
- Rather than using the databases' native query language (e.g. SQL), you can use an Object Data Model ("ODM") / Object Relational Model ("ORM"). An ODM/ORM represents the website's data as JavaScript objects, which are then mapped to the underlying database. Some ORMs are tied to a specific database, while others provide a database-agnostic backend.
- Pros
- Easier for programmers can continue to think in terms of JavaScript objects rather than database semantics
- Provide an obvious place to perform validation and checking of data
- Cons
- Less performant than native query languages
- Pros
- Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
- Installing Mongoose and MongoDB
npm install mongoose
- Mongoose requires a connection to a MongoDB database. You can require() and connect to a locally hosted database with mongoose.connect(), as shown below.
//Import the mongoose module var mongoose = require('mongoose'); //Set up default mongoose connection var mongoDB = 'mongodb://127.0.0.1/my_database'; mongoose.connect(mongoDB, { useNewUrlParser: true }); //Get the default connection var db = mongoose.connection; //Bind connection to error event (to get notification of connection errors) db.on('error', console.error.bind(console, 'MongoDB connection error:'));
-
Models are defined using the Schema interface.
-
The Schema allows you to define the fields stored in each document along with their validation requirements and default values.
const mongoose = require('mongoose'); const superHeroSchema = new mongoose.Schema({ name: String });
-
A SchemaType is then a configuration object for an individual property.
-
Schemas are then "compiled" into models using the
mongoose.model()method.const SuperHeroModel = mongoose.model('SuperHeroModel', superHeroSchema);
-
The following are all the valid SchemaTypes in Mongoose. Mongoose plugins can also add custom SchemaTypes:
-
Mongoose provides built-in and custom validators, and synchronous and asynchronous validators.
-
The built-in validators include:
- All SchemaTypes have the built-in required validator. This is used to specify whether the field must be supplied in order to save a document.
- Numbers have min and max validators.
- Strings have:
var superHeroSchema = new Schema({ movieCount: { type: Number, min: [0, 'Too few movies'], max: 12, required: [true, 'Why no movies?'] }, brand: { type: String, enum: ['Marvel', 'DC'] } });
-
While you can create schemas and models using any file structure you like, we highly recommend defining each model schema in its own module (file), exporting the method to create the model.
./models/superhero.model.js
const mongoose = require('mongoose'); const superHeroSchema = new mongoose.Schema({ name: String }); module.exports = mongoose.model('SuperHeroModel', superHeroSchema);
- An instance of a model is called a document. Creating them and saving to the database is easy.
var SuperHeroModel = require('../models/superhero.model') var hero = new SuperHeroModel({ name: 'WOLVERINE' }); hero.save(function (err) { if (err) return handleError(err); // saved! }); // or SuperHeroModel.create({ name: 'WOLVERINE' }, function (err, small) { if (err) return handleError(err); // saved! }); // or, for inserting large batches of documents SuperHeroModel.insertMany([{ name: 'WOLVERINE' }], function(err) { });
- Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.
SuperHeroModel.find({ name: 'WOLVERINE' }).where('createdDate').gt(oneYearAgo).exec(callback);
- Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.
SuperHeroModel.deleteOne({ brand: 'DC' }, function (err) { if (err) return handleError(err); // deleted at most one tank document }); SuperHeroModel.updateOne({ name: 'WOLVERINE' }, { name: 'LOGAN' }, function(err, res) { // Updated at most one doc, `res.modifiedCount` contains the number // of docs that MongoDB updated });
- Models have static deleteOne() and deleteMany() functions for removing all documents matching the given filter.
SuperHeroModel.deleteOne({ brand: 'DC' }, function (err) { if (err) return handleError(err); // deleted at most one tank document });