Getting Started with NoSQL Databases using MongoDB

15 November, 2015
post-banner

In this article we're going to be looking at MongoDB, and how to get started by creating a database and running CRUD commands on the data.

MongoDB is an open-source NoSQL database. MongoDB was created in 2007 with the intention of being sold as a product, but was then moved to open-source development in 2009 after gaining popularity. Since July 2015, MongoDB is now the fourth most popular type of database management system and is the most popular NoSQL database. MongoDB uses CRUD operations to manage the data in the database, which we'll explore later in the tutorial.

SQL vs. MongoDB

A NoSQL database is basically a database that isn't relational. They were generally designed to deal with scaling much better than SQL databases.

NoSQL databases have dynamic schemas, which means that the schema for a particular collection of data doesn't have to be defined before data is added, unlike SQL databases. This is great for agile development styles where your database structure may not be determined yet.

MongoDB uses a JavaScript-style query language rather than something like SQL. If you're using a full JavaScript-stack application, this will make the Mongo queries you write more relatable to the rest of the code base. It is a document orientated database which means it is great for large amounts of unstructured data.

Inside the database are collections, which is a somewhat similar version of a SQL table. Inside of a collection is a group of documents, or rows in SQL. Documents are basically JSON-like objects, using the BSON format.

Instead of using joins to combine data from two ore more SQL tables, MongoDB uses embedded documents for linking data between documents. This means that you can insert a sub-document to be embedded into a document that it links with. For more information on Mongo's data modelling check out the manual.

Since Mongo documents exist independently, documents inside the same collection are able to have different fields. This is great because it allows you to create documents inside a collection that have different fields, but can still be queried by their specific shared fields.

Installation & Setup

So, let's get started using a MongoDB database.

For the purposes of this article, I will show you how to install MongoDB on OS X. If you wish to install on a Linux or Windows system you can check the MongoDB docs for a simple walkthrough on how to do this.

You can install MongoDB with Homebrew. Open up your terminal and enter the following commands.

$ brew update
$ brew install mongodb

To be able to start using MongoDB, you have to run the process at the command line.

$ mongod

This will start the MongoDB process and it should tell you that it is waiting for connections on port 27017. The following output will be displayed in the terminal.

mongod-start

Now open up a new terminal window (CMD + T) while mongod is still running. Next all you need to do to connect to the MongoDB service is run mongo which will start the mongo shell. You will then be able to enter mongo commands at the > prompt.

$ mongo

MongoDB shell version: 3.0.7  
connecting to: test  
Server has startup warnings:  
2015-11-14T13:50:47.709+0000 I CONTROL  [initandlisten]  
2015-11-14T13:50:47.709+0000 I CONTROL  [initandlisten] ** WARNING: soft rlimits too low. Number of files is 256, should be at least 1000  
> 

If you would like to shut the mongo server down, just run the following commands in your mongo instance.

> use admin
> db.shutdownServer()

Basic Mongo Commands

Now that a Mongo instance has been started, we can now select a database and begin to use it. One of the great things about MongoDB is that the shell commands are relatively simple and easy to remember, which is good for people for aren't completely comfortable with the command line.

  • > help - Show list of all available commands
  • > db - Return the current database
  • > use db_name - Switch to specified database, and create it if it does not exist
  • > show dbs - Return a list of all databases
  • > show collections - Return a list of collections from the current database

You don't have to enter the > character as this is just to show that the command should be entered at the Mongo prompt. If you are not seeing this in your terminal then you might need to run the mongo command again.

CRUD Commands

So in this article we will create a new database, and learn how to use CRUD (Create, Read, Update, Delete) commands for manipulating documents in Mongo. Let's create a new database called 'learn_mongo' (or anything you want to call it).

> use learn_mongo

Create Documents

We are now going to create a collection called 'books' and add some documents to it.

You can create a new collection by simply inserting a new document to an non-existent collection. Let's add a 'book' document to a new 'books' collection.

> db.books.insert(
  {
    "title" : "Kafka on the Shore",
    "author" : "Haruki Murakami",
    "publish_year" : 2002,
    "genre" : ["fiction", "magical realism"]
  }
)

When this code is entered into the mongo shell, a new document is created inside of the 'books' collection. We have added string values for the title and author, a number for the publish year and an array of all genres associated with the specific book.

The mongo shell will return a 'WriteResult' to give us confirmation that the document has been inserted:

WriteResult({ "nInserted" : 1 })  

There is no need to add a unique ID to the document on insert, as mongo will sort this out for us. We could also use other data types such as objects, booleans, null or ISODate. An ISODate will add a date to the field of the document, but you should note that the months start at 0 (just because), so to specify a date of 15/11/2015, for example, you would have to enter the following:

...
  {
    "date" : new Date(2015, 10, 15)
  }

Another great thing about Mongo is that we don't have to use the same fields for every document we insert to a collection. This can be very useful if some data only applies to very specific documents.

> db.books.insert(
  {
    "title" : "Lolita",
    "author" : "Vladimir Nabokov",
    "publish_year" : 1955,
    "genre" : ["Russian literature", "fiction"],
    "isbn" : "9780141182537"
  }
)

So here, for example, we have added a new document to the existing 'books' collection with an additional field for the 'isbn', and the insertion is still valid.

Validations

It is important to check that the data you are entering is valid before you save it to the database. This is because Mongo's validation checks will not make sure that data is unique or relevant. The validation checks that are run are:

  • Document has a unique id (ObjectId)
  • No syntax errors in the shell script
  • Document is less than 16mb

Read Documents

Now that we have some documents inside the collection, we are able to query this data to find and return the books that we want to find.

To return a list of all documents in the collection we can run db.books.find().

> db.books.find()

{ "_id" : ObjectId("5648b71173f5359ec5e31500"), "title" : "Kafka on the Shore", "author" : "Haruki Murakami", "publish_year" : 2002, "genre" : [ "fiction", "magical realism" ] }
{ "_id" : ObjectId("5648ba2373f5359ec5e31501"), "title" : "Lolita", "author" : "Vladimir Nabokov", "publish_year" : 1955, "genre" : [ "Russian literature", "fiction" ], "isbn" : "9780141182537" }

The output shows all of the data we have inserted into the database collection, along with the generated ObjectId for each document.

In Mongo we can query the collection by specific fields inside of a document. For example, we could search our book collection by author or title strings, by the publish year or by specific array values in the genre array. To show this more clearly, I've inserted several new documents to the collection.

> db.books.find({"author":"Haruki Murakami"})

{ "_id" : ObjectId("5648b71173f5359ec5e31500"), "title" : "Kafka on the Shore", "author" : "Haruki Murakami", "publish_year" : 2002, "genre" : [ "fiction", "magical realism" ] }
{ "_id" : ObjectId("5648bd1173f5359ec5e31502"), "title" : "Norwegian Wood", "author" : "Haruki Murakami", "publish_year" : 1987, "genre" : [ "Japanese literature", "fiction" ] }
> db.books.find({"genre":"Russian literature"})

{ "_id" : ObjectId("5648ba2373f5359ec5e31501"), "title" : "Lolita", "author" : "Vladimir Nabokov", "publish_year" : 1955, "genre" : [ "Russian literature", "fiction" ], "isbn" : "9780141182537" }

Update Documents

Let's say that I have just inserted a new document to the books collection, which should have be by the author 'Haruki Murakami'. But when I tried to run a query to list all of the book documents by Haruki Murakami, the new one is missing, because there was a spelling error when I inserted the record.

> db.books.update (
  {"title" : "What I Talk About When I Talk About Running"},
  {"$set" : {"author" : "Haruki Murakami"}}
)

Updates are simply done using a query parameter and an update operator ($set). Updates will only be done for the first document to be matched, unless we specify otherwise. We will then be returned with the amount of documents matched, amount of documents inserted and the amount of documents modified.

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

If we want to update all matching records we only need to add {"multi" : true} after the update parameter in the query.

Delete Documents

Deleting documents is done in much the same way. ALl we need to do is specify db.books.remove and then a query for all documents we want to delete. Unlike updating documents, all of the matches will be removed, so be careful with the queries you run.

> db.books.remove(
  {"author" : "George Orwell"}
)

This will delete all documents from the books collection that were set to the author 'George Orwell'. We will then be displayed with a 'WriteResult' telling us that 2 documents were removed.

WriteResult({ "nRemoved" : 2 })  

As you can see, using CRUD commands in a MongoDB database is pretty simple and the syntax is all familiar and it's easy to understand what is happening to the data. This is all you need to get started with MongoDB, but there are many more advanced data modification commands that can be used to manipulate data documents.

Advanced Modification of Documents

MongoDB allows us to use operators to further modify our data. These are used in much the same way as the $set operator and can be used alongside a query to modify specific documents. As before, we will be returned with a 'WriteResult' to inform us of all matches, upsertions and modifications inside the collection.

$unset

The $unset operator allows us to remove fields from a document.

> db.books.update(
  {},
  {"$unset" : {"isbn" : ""}},
  {"multi" : true}
}

The empty {} curly brackets allow us to query all books in the collection, and setting the 'isbn' to empty "" speech marks will remove the field. Again "multi" : true allows us to apply this update to all matches.

$rename

The $rename operator allows fields to be renamed. This is done in exactly the same way as $unset by simply specifying $rename instead.

> db.books.update(
  {},
  {"$rename" : {"author" : "writer"}},
  {"multi" : true}
)

Other useful update operators

There are many more useful update operators that can be used in your MongoDB database. Check out the MongoDB 'Manual' for great documentation on this.

  • $max - Update matched documents if new value is greater than current value.
  • $min - Update matched documents if new value is less than current value.
  • $mul - Multiply the current value by the value set.
  • $pop - Remove first or last array value (-1 for first, 1 for last).
  • $push - Add new value to the end of array.
  • $addToSet - Add new value to the end of array if the value is unique.
  • $pull - Remove value from the arrau.

GUI for MongoDB

If you're not too keen on running everything using the command line, then there is a great GUI tool available to manage your MongoDB database instead.

RoboMongo is an open-source MongoDB management tool that embeds the same JavaScript engine that runs the mongo shell. There are a whole bunch of great features provided and setup is real simple. To use the database we have been working on, click 'create' and then enter 'learn_mongo' (or whatever you called it) as the name.

robomongo

As you can see we have a great visualisation of the data we have been working with, and you are able to run queries and operations of the database using the GUI.

Conclusion & Further Reading

So, in the near future, I'm planning to write more articles around using MongoDB with Node/Mongoose and getting started with MEEN/MEAN stack applications. Hopefully this article was useful in getting a MongoDB database running and learning how to use simple CRUD operations to manipulate your data.

Here are some pretty cool resources for reading more about MongoDB:

comments powered by Disqus