The MEAN Stack - MongoDB

In the previous post on MEAN stack, you have learnt how to install MongoDB and start the mongod service. In this post you will learn enough to get you started with Mongo from a developer perspective. I am purposely leaving out a lot of details so that you can get upto speed as quickly as possible.

What is Mongod?

Mongod is the deameon that you have learnt about in the previous post as well. For a quick refresh, here is what you need to do to run it:

mongod --dbpath ~/Desktop/Workbench/MongoDatabases

Starting it using --dbpath is one way. Another way is to create a default path, and simply start the deamon by executing mongod. Mongo listens on port 27017, so you need to ensure no other application is using that port.

sudo mkdir -p /data/db

How to connect to Mongod?

You will need to use Mongo Shell (simply type mongo in your terminal and hit enter). You can view help to learn more. It is an extremely handy command while working with the shell.

help

What are documents?

From a data structure point of view, they are like Dictionaries => typical structures with Keys and Values. Mongo documents are quite similar to JSON but the format is BSON which is a binary representation of JSON. The benefit it brings to the table is that it has additional data types. More on this when we work with objects.

What are Collections?

Collection is group of related documents. Think of it as a Table in a typical RDBMS software. A collection exists within a single database and they do NOT have a schema. Just like tables, a collection is supposed to have similar documents, even though there is no schema enforcement.

How to create a Database?

This is where the real fun starts. Let us create a new database called mydata

use mydata

Let’s see if the database is created yet. Try to list all databases:

show dbs

You will not see anything yet, except local & test. Don’t worry about it. Let’s insert a record straight away and you will notice that db will appear. In an RDBMS you typically start with create different tables and set the security. Not with Mongo! However, just because you are not using RDBMS doesn’t mean you should be careless about schema. It requires planning, but it is more flexible. For now, let me cut it short and simply show you the basics. In the coming posts, I will share more about the best practices, etc.

Where is my table?

Here you go: simply running this insert command will create a collection (like a table) called customer and insert a document (like a record) which has a name and a contact. Any valid JSON can be inserted this way.

db.customer.insert({ "name":"Customer1","contact":"customer1@somewhere.com" })

When you run the command above, you should see an output like so:

WriteResult({ "nInserted" : 1 })

This tells you that 1 record was inserted successfully.

How can I view my records?

Simply type the following, and you should be able to find a record:

db.customer.find()
{ “_id” : ObjectId(“55fe4940b30a4d6e50e6418a”), “name” : “Customer1”, “contact” : “customer1@somewhere.com” }

Neat! Isn’t it? It automatically created an _id property and assigned a unique id to our record. This is handy.

How can I delete all records?

Well, if you are good with finding the records, you can delete them fairly easily. I haven’t yet explained how to find the records. Let’s clear the customer that we added just now. Use the following command:

db.customer.remove({})

An empty parameter {} means, delete everything. For now, there is no harm doing it, but you can see how dangerous this command can be. That’s one reason why I have shown this to you initially.

Viewing all collections and deleting the ones you want

As you can guess, the customer collection still exists (we have just deleted the records!). Let’s view all collections.

show collections

To drop the customer collection, use the following command:

db.customer.drop()

It will return true if successful.

How can I insert multiple records?

Well, Mongo provides a pretty decent set of records which will help us play with the data. You can view the schema here: For now, download the data using the browser, or use the following command.

curl https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/dataset.json > database.json

To import all this data into your collection, run this command:

mongoimport --db mydata --collection restaurants --drop --file database.json

Notice that I am using the same mydata database. The collection name is restaurants. –drop tells mongoimport to drop the collection if it exists, and –file tells which file to import. This is what I got in my terminal: (it took less than 800ms to import 25K+ documents)

2015-09-20T11:42:22.117+0530 connected to: localhost
2015-09-20T11:42:22.118+0530 dropping: mydata.restaurants
2015-09-20T11:42:22.938+0530 imported 25359 documents

How to find records using top-level filters?

You need to use the find() method and keep in mind a simple rule. The queries are scoped to a single collection. Since your collection contains JSON, you can easily nest the objects and reap the rewards of NoSQL. No need to use JOINs! If you take a look at the records in restaurants table, you can see how neatly it has been categorised and has nested information. View the first record using a very obvious command. This information is enough to tell you a bunch of things about the restaurants. As you can guess, it would have taken quite an exercise from an RDBMS system to return a similar result set!

db.restaurants.find()[0]

You can count the number of records using:

db.restaurants.find().count()

How to find all Bakers?

db.restaurants.find({'cuisine':'Bakery'})

As can be seen from the above schema ‘cuisine’ is at the top level and ‘Bakery’ is the value. The query above will return all objects which have cuisine set to Bakery. Notice that the search is case-SenSITive!

How to find all Bakers but show (Project) only the name & restaurant_id?

db.restaurants.find({'cuisine':'Bakery'}, {name:1, restaurant_id:1})

You can tell Mongo to return ONLY name and restaurant_id and it will oblige you. However, it will also return _id field. This field is returned for every query. name:1 signifies show the field. The output will look something like this:

{ “_id” : ObjectId(“55fe4e4637dbf04ca2bc5630”), “name” : “Morris Park Bake Shop”, “restaurant_id” : “30075445” }
{ “_id” : ObjectId(“55fe4e4637dbf04ca2bc5652”), “name” : “Olive’S”, “restaurant_id” : “40363151” }
{ “_id” : ObjectId(“55fe4e4637dbf04ca2bc5791”), “name” : “Tropical House Baking Co.”, “restaurant_id” : “40372596” }
{ “_id” : ObjectId(“55fe4e4637dbf04ca2bc5856”), “name” : “Cousin John’S Cafe And Bakery”, “restaurant_id” : “40383763” }

If you want to hide certain fields you can set that field to 0.

db.restaurants.find({'cuisine':'Bakery'}, {name:1, restaurant_id:1, _id:0})
Sample output (stripped){ “name” : “Morris Park Bake Shop”, “restaurant_id” : “30075445” }
{ “name” : “Olive’S”, “restaurant_id” : “40363151” }
{ “name” : “Tropical House Baking Co.”, “restaurant_id” : “40372596” }
{ “name” : “Cousin John’S Cafe And Bakery”, “restaurant_id” : “40383763” }
{ “name” : “Victory Sweet Shop”, “restaurant_id” : “40384920” }

Find using nested fields What if you find all local restaurants? Let’s try to filter using the zip code.

You guessed it, JavaScript’s DOT notation!

db.restaurants.find({"address.zipcode":"10462"}, {"name":1, "_id":0})
Sample output (stripped){ “name” : “Morris Park Bake Shop” }
{ “name” : “The New Starling Athletic Club Of The Bronx” }
{ “name” : “Lulu’S Coffee Shop” }

Same holds true for arrays. For ex. if you like, you can search for grades using the dot notation as well.

You can now see which way we are going. Mongo makes a database look like a string of JSON and brings the goodness of JavaScript. I have barely touched the surface so far, but I am sure you would have got an idea of why having Mongo can be a huge benefit in today’s world.

Other operators for Find

So far, you have seen how to use eqality operator while finding. What if you want to find every restaurant where grade score is greater than 60?

db.restaurants.find({"grades.score": {$gt: 60}},{name:1, _id:0})

Similarly you can use $lt for less than operator.

Logical operators – AND

To combine multiple operators is not hard either. For AND, you need to use multiple conditions, like so:

db.restaurants.find({"cuisine":"Bakery", "grades.score":{$gt:50}}, {name:1, _id:0})

This will find all restaurants where cuisine is Bakery and the grades.score is greater than 50. This will help me satisfy my sweet tooth!

Logical operators – OR

OR happens to be a bit trickier. I need a decent Pasta before I go for the donut! Let’s try this to get a list of Italian restaurants and Bakeries.

db.restaurants.find({ $or: [ {"cuisine":"Bakery"}, {"cuisine":"Italian"}] })

Logical operators – OR and AND together

Well, I found the list of restaurants, but I am not in a mood for long drives. How about finding the Bakery and Italian restaurants in a specific zip code.

db.restaurants.find({ $or:[{"cuisine":"Bakery"}, {"cuisine":"Italian"}], "address.zipcode":"10462"}, {name:1, cuisine:1,_id:0})

As you can see, you can use OR and AND together just as easily. Try getting a similar resultset using tables in RDBMS as easily!

Update Records

Every field can be updated in Mongo just as easily except, _id. By default, update() method updates only 1 record. Let’s see if there are multiple records with a specific name.

db.restaurants.find({"name":"Morris Park Bake Shop"}).count()

You will see the output as 1.

This is good. Let’s update the name to be Baker instead of Bake. The first portion of update method filters the record, and the second portion uses $set to set all fields. There are plenty of other use cases which you can read here.

db.restaurants.update({"name":"Morris Park Bake Shop"}, {$set:{"name":"Morris Park Baker Shop"} })

Remove records

Removing records can’t get easier! The following command will remove every restaurants in Manhattan (sorry folks!).

db.restaurants.remove( { "borough": "Manhattan" } )

If you would like to remove just one, you can pass, justOne: true, like so:

db.restaurants.remove( { "borough": "Brooklyn" }, {justOne:true} )

You have already seen how to remove all records earlier in this post. Just to reiterate, use the following command and all the restaurants will be deleted. (Ouch!)

db.restaurants.remove({})

Let’s import all of them back, so that you can play with it again… exit Mongo, and run the following in the terminal again.

mongoimport --db mydata --collection restaurants --drop --file database.json

Conclusion

Mongo is great at what it does. If you have been following along, I hope you got a gist of how to do the basics in Mongo. I would urge you to attend their free online courses and take your Mongo expertise to the next level.

© 2023, Attosol Private Ltd. All Rights Reserved.