MongoDB Tutorial
MongoDB tutorial for beginners#
I am starting this tutorial assuming you already have MongoDB installed and running on your system. If you haven't installed it yet, get it installed first.
Ok, now that you have MongoDB installed, let's proceed with the tutorial.First, let's have the MongoDB server running:
$ mongod
Then let's connect to the server using the mongo client:
$ mongo
Note that all the commands in the tutorial will be typed at the mongo client's command prompt >
.
Getting acquainted with MongoDB
MongoDB is a document-oriented database system (a kind of NoSQL) made up of the hierarchy of database > collection > document > field > key:value. Here is an approximate comparison between MongoDB and SQL data models.
MongoDB : SQL
---------------------
database : database
collection : table
document : row
field : -
{key:value} : -
The similarity (distant) ends at the SQL's row level. It is a good idea to remember the above comparison because I will switch entirely to Mongo-esque from SQL-esque - no more terms like table, row etc.
Next thing to note: the Mongo shell is a fully functional JavaScript shell. You can perform JavaScript operations on data before inserting to or retrieving from the database. The shell supports all standard JavaScript API along with some Mongo-specific custom APIs. I think this feature makes MongoDB an extremely powerful and fascinating database system.
Before you get your hands dirty with the data in the database, I think you should know how to deal with the database system first. Here are the basics of how you interact with MongoDB.
To see the list of databases in the system:
> show dbs
bands 0.203125GB
movies (empty)
scores (empty)
Just like in SQL, you need to first select a database to be able to perform operations on it. To select a database:
> use movies
switched to db movies
To find out the currently selected database:
> db.getName()
movies
To delete / drop a database, make sure you have selected the database and then do this:
> use scores
> db.dropDatabase()
{"dropped" : "scores", "ok" : 1 }
To see the collections in a databases:
> show collections
or
> db.getCollectionNames()
Unlike in SQL, databases in MongoDB are created lazily. You don't create databases using any explicit commands. Depending on your commands, the system creates it for you once it determines a database needs to be created. To begin creating a new database, first execute the use
command to switch to a new database, and then issue a command which saves some data to the database - this results in the creation on the new database.
Let's create a new database named "movies":
> use movies
switched to db movies
> db.comedy.insert({name:"Bill & Ted's Excellent Adventure", year:1989})
That above commands resulted in the creation of the new database named "movies". In the process a new collection called "comedy" was also created in the database.
Now that you know how to handle the database, time to get your hands dirty with the data in the database!
Getting your hands dirty with data in MongoDB
What good is a MongoDB tutorial that does not show how CRUD (Create, Read, Update, Delete) works in MongoDB, preferably with examples? As this tutorial aims to be the best MongoDB tutorial in the world it will show you how CRUD works in MongoDB.
Note: all database commands are called on the MongoDB database object named db. db refers to the database you have selected using the use
command.
Create / add data in MongoDB
To create documents in a collection:> db.comedy.insert({name:"Wayne's World", year:1992})
> db.comedy.insert({name:'The School of Rock', year:2003})
The two commands above added two more documents to the collection named "comedy" in the "movies" database.
You could have done the same thing using the save
command instead of the insert
command.
> db.comedy.save({name:"Wayne's World", year:1992})
> db.comedy.save({name:'The School of Rock', year:2003})
The difference between insert
and save
is this:
insert
will always add a new document. save
does an insert
if there is no _id
key in the object it receives, else it does an update
.
I personally see save
to be quite pointless. Unless you are too hooked to the spelling and sound of save, it is recommended to use insert
to add new documents to a collection, and update
to update collections.
Read data from MongoDB
To read data from a collection:> db.comedy.find()
{ "_id" : ObjectId("4e9ebb318c02b838880ef412"), "name" : "Bill & Ted's Excellent Adventure", "year" : 1989 }
{ "_id" : ObjectId("4e9ebb478c02b838880ef413"), "name" : "Wayne's World", "year" : 1992 }
{ "_id" : ObjectId("4e9ebd5d8c02b838880ef414"), "name" : "The School of Rock", "year" : 2003 }
That got the whole collection. To limit it to just two:
> db.comedy.find().limit(2)
{ "_id" : ObjectId("4e9ebb318c02b838880ef412"), "name" : "Bill & Ted's Excellent Adventure", "year" : 1989 }
{ "_id" : ObjectId("4e9ebb478c02b838880ef413"), "name" : "Wayne's World", "year" : 1992 }
Similar to using find().limit(1)
, there is a function called findOne()
, which will get you only one document in the result.
db.comedy.findOne()
{
"_id" : ObjectId("4e9ebb318c02b838880ef412"),
"name" : "Bill & Ted's Excellent Adventure",
"year" : 1989
}
What if you want to conditionally find documents?
> db.comedy.find({year:{$lt:1994}})
{ "_id" : ObjectId("4e9ebb318c02b838880ef412"), "name" : "Bill & Ted's Excellent Adventure", "year" : 1989 }
{ "_id" : ObjectId("4e9ebb478c02b838880ef413"), "name" : "Wayne's World", "year" : 1992 }
In the above example we looked for documents with their year field with value less than 1994. The $lt
you saw are one of the many conditional operators in MongoDB. Here are the rest.
$lt - ' $lte - ' $gte - '>='
$ne - '!='
$in - 'is in array'
$nin - '! in array'
And how do we do an 'equal to' (==) query? Just match the value for the queried key:
> db.comedy.find({year:1992})
{ "_id" : ObjectId("4e9ebb478c02b838880ef413"), "name" : "Wayne's World", "year" : 1992 }
We can even use regular expressions in our queries!
> db.comedy.find({name:{$regex: /bill|steve/i}})
{ "_id" : ObjectId("4e9ebb318c02b838880ef412"), "name" : "Bill & Ted's Excellent Adventure" }
Now let's try a more complicated use of regex in a query.
> var names = ['bill', 'steve']
> names = names.join('|');
> var re = new RegExp(names, 'i')
> db.comedy.find({name:{$regex: re}})
{ "_id" : ObjectId("4e9ebb318c02b838880ef412"), "name" : "Bill & Ted's Excellent Adventure" }
What if you want to get only some fields in the result?
> db.comedy.find({year:{'$lt':1994}}, {name:true})
{ "_id" : ObjectId("4e9ebb318c02b838880ef412"), "name" : "Bill & Ted's Excellent Adventure" }
{ "_id" : ObjectId("4e9ebb478c02b838880ef413"), "name" : "Wayne's World" }
In the above example, we excluded a field by not specifying it in the second parameter of the find()
function. To get more than one exclusive fields in the results you might do something like db.comedy.find({year:{'$lt':1994}}, {name:true, director:true})
. Note, the director field is still not set, so you won't see any director info.
The _id
field is always returned by default. If you want to get rid of it, you need to explicitly do so using the option explained next.
What if you want to get all, except some fields in the result?
> db.comedy.find({year:{'$lt':1994}}, {name:false})
{ "_id" : ObjectId("4ed201525bfc796ab22f9ee1"), "year" : 1989 }
{ "_id" : ObjectId("4ed201605bfc796ab22f9ee2"), "year" : 1992 }
Unfortunately, as of this writing field inclusion and exclusion cannot be used together.
I want to show you some interesting Mongo-specific queries (using the dot notation), so let's create some documents in a collection named 'articles':
> db.articles.insert({title:'The Amazingness of MongoDB', meta:{author:'Mike Vallely', date:1321958582668, likes:23, tags:['mongo', 'amazing', 'mongodb']}, comments:[{by:'Steve', text:'Amazing article'}, {by:'Dave', text:'Thanks a ton!'}]})
> db.articles.insert({title:'Mongo Business', meta:{author:'Chad Muska', date:1321958576231, likes:10, tags:['mongodb', 'business', 'mongo']}, comments:[{by:'Taylor', text:'First!'}, {by:'Rob', text:'I like it'}]})
> db.articles.insert({title:'MongoDB in Mongolia', meta:{author:'Ghenghiz Khan', date:1321958598538, likes:75, tags:['mongo', 'mongolia', 'ghenghiz']}, comments:[{by:'Alex', text:'Dude, it rocks'}, {by:'Steve', text:'The best article ever!'}]})
To search an object inside an object, just use the regular JavaScript dot notation of the target object as the key AND quote it. For example, to query the meta.likes
object, you might do something like this:
> db.articles.find({'meta.author':'Chad Muska'})
> db.articles.find({'meta.likes':{$gt:10}})
You need to query an array? No problem:
> db.articles.find({'meta.tags':'mongolia'})
When the key is an array, the database looks for the object right in the array.
You need to look for an object inside an array? No problemo:
> db.articles.find({'comments.by':'Steve'})
You can also refer to array indexes:
> db.articles.find({'comments.0.by':'Steve'})
Isn't that amazing?
Because of the fact that array objects can be matched using the dot notation, it can be problematic if the objects in an array share the same keys but different values. In such cases, we need to use the $elemMatch
operator. To see an example and understand the issue better, read this.
Always remember that a quoted number is a string, and is not the same as the actual number. For example:
> db.students.find({score:100})
is totally different from
> db.students.find({score:'100'})
In general, form request parameters come as strings, so you are likely to be querying for the stringified version of numbers in your web apps if you use the parameters as such. Make sure to convert them to their number equivalent wherever necessary first. For example in Express, you can do this:
var score = +params.score;
params.score
is a string, but score
is now an actual JavaScript number, which can be reliably used in a MongoDB query.
MongoDB queries support JavaScript expressions! Take a look at this example:
> db.comedy.find('this.year > 1990 && this.name != "The School of Rock"')
does the same thing as:
> db.comedy.find({year:{$gt:1990}, name:{$ne:'The School of Rock'}})
But note that the flexibility of JavaScript expressions comes at a price - it is slower than native MongoDB operators.
MongoDB has another operator called $where
using which you can perform SQL's WHERE-like operations.
> db.comedy.find({$where: 'this.year > 2000'})
{ "_id" : ObjectId("4ed45fae2274c776f9179f89"), "name" : "The School of Rock", "year" : 2003 }
and
> db.comedy.find({name:'The School of Rock', $where: 'this.year > 2000'})
{ "_id" : ObjectId("4ed45fae2274c776f9179f89"), "name" : "The School of Rock", "year" : 2003 }
Again, like JavaScript expressions $where
is slower than native operators. Use JavaScript expressions and $where
ONLY when you can't accomplish the query using native operators.
It is highly recommended that you go through all the advanced MongoDB query operators once you are done with this tutorial.
Update data in MongoDB
Let's try adding a new field for one of the documents. What comes to your mind instantly might look something like this:> db.comedy.update({name:"Bill & Ted's Excellent Adventure"}, {director:'Stephen Herek'})
HOLD IT! That's about to do something disastrous. It will overwrite the whole document with {director:'Stephen Herek'}
, instead of updating it by appending a new field.
The right way to do is:
> db.comedy.update({name:"Bill & Ted's Excellent Adventure"}, {'$set':{director:'Stephen Herek', cast:['Keanu Reeves', 'Alex Winter']}})
The above command will reorder the fields, but worry not, the data in safe and intact.
Now how do you update a value which is an array?
> db.comedy.update({name:"Bill & Ted's Excellent Adventure"}, {'$push':{cast:'George Carlin'}})
> db.comedy.update({name:"Bill & Ted's Excellent Adventure"}, {'$push':{cast:'Chuck Norris'}})
Eh, we need to remove something from the cast array. We do it this way:
db.comedy.update({name:"Bill & Ted's Excellent Adventure"}, {'$pull':{cast:'Chuck Norris'}})
As easy as that! But there's lot more to updating that just those, for details click here.
Delete data in MongoDB
How do you delete a field from a document?> db.comedy.update({name:'Hulk'}, {$unset:{cast:1}})
In case you want to delete a field from all the document of a collection:
> db.comedy.update({$unset:{cast:1}}, false, true)
The false
parameter if for upsert option, true
is for multiple option. We set multiple option to true
because we want to delete them all from the collection. In my opinion this is an inconsistency. It should work like find()
and findOne()
, when it comes to selection.
How do you delete a document from a collection?
> db.comedy.remove({name:'Hulk'})
In the above example, we deleted all the documents with their name field set as Hulk.
How do you empty a collection of its documents?
> db.comedy.remove()
Note, the above command does not delete the collection, it just 'resets' the collection like the SQL truncate
command.
How do you delete / drop a collection?
> db.comedy.drop()
The above command actually deletes the collection.
To delete a database select the database and call the db.dropDatabase()
on it:
> use movies
> db.dropDatabase()
{"dropped" : "movies", "ok" : 1 }
That deletes the database named movies
.
Get the count of Documents / Records
Any good database system should have a count()
method which returns the number of records that will be returned for a query. MongoDB too has a count()
method which you can call on a collection to get the count of the results.
This will return the total number of documents in the collection named comedy
:
> db.comedy.count({})
This will return the total number of documents in the collection named comedy
with the value of year
more than 1990:
> db.comedy.count({year:{$gt:1990})
So basically that's about it. There is a ton more to MongoDB than what I covered, I have listed the pointers at the Further Reading section, read all of them.
I hope you found this tutorial useful. I will be writing many more MongoDB related articles and tutorials in the future, so stay tuned. If you have any orientation / beginner level questions, feel free to ask me in the comments.