Home / Blogs / mongodb

MonoDB: NoSQL Database

Published May 4, 2024
By Soumik Ghosh
MonoDB: NoSQL Database

What kind of Database is it?

Databases can be categorized based on how they store and manage data. Unlike traditional databases like MySQL, which use a table format to store data, MongoDB uses a different approach where data is stored in a JSON-like format. This type of database is known as a NoSQL database.

SQL-based databases (such as MySQL, Oracle SQL, etc.) are table-based databases where each row represents a new record and each column represents a specific attribute of the data. The tables are organized in a way that columns are related to each other, forming a structured, relational schema.

NoSQL databases (such as MongoDB, HBase, etc.) are document-oriented databases where each document is a new record, and they are stored in a manner as in parking cars beside each other, allowing for more flexible and scalable data models.

About MongoDB

MongoDB is a NoSQL document based database which stores data in JSON like format called BSON (BSON stores data in a binary format, it also has support for data-type like date, and numeric specific numeric types). In MongoDB, database contains collections, each collection stores documents and each document is a set of key value pair. Values can be nested documents or arrays. This structure allows flexible and schema-less data modeling.

Here is a representation of MongoDB document:

1{
2	_id: ObjectId("5eb3d66831de5d88f4305b"),
3	name: "Soumik",
4	age: 22
5}

Database

Show all databases:

show dbs

Create a new database/ Select an existing database:

use database_name

Check which database you are in:

db

Collections

Show all collections:

show collections

View all data from the collection:

db.collection_name.find()

Create collection:

db.createCollection("new_collection")

Insert Document

To insert a single document in a collection:

db.collection_name.insertOne( { name: "soumik", age: 22 } )

(you should see output as acknowledged: true and an ObjectId will be returned)

To insert multiple document:

db.collection_name.insertMany( [ {name: "smik", age: 22}, {name: "xyz", age: 21} ] )

(like insertOne you will get an output acknowledged as true and two ObectId will be returned for two document)

Find Document

To see all the documents in a collection:

db.collection_name.find()

To see a single document in a collection:

db.collection_name.findOne()

Filter Data:

Show data based on one condition:

db.collection_name.find( { name: "soumik" } )

Show data based on multiple condition:

db.collection_name.find( { name: "soumik", age: 22 } )

Show only certain fields from the document:

db.collection_name.find( {}, { name: 1, age: 0 } )

0 value will hide the certain field and 1 will show it

Now, sometimes the document might be embedded inside parent document, the structure will look something like this..

1{
2	_id: ObjectId("5eb3d66831de5d88f4305b"),
3	name: "Soumik",
4	age: 22
5	address{
6		street: "xyz street",
7		building: 23,
8		zipcode: 111111
9	}
10}

To search by embedded document values:

db.collection_name.find( { "address.zipcode": 111111 } )

Comparison Operator:

$eq : values are equal

$ne : values aren't equal

$lt : left value is less than right value

$gt : left value is greater than right value

$lte : left value is less than equals to right value

$gte : left value is greater than equals to right value

An example of comparison operator :

db.collection_name.find( { age: {$gt : 20} } )

This will show all the documents which has age greater than 20.

Sort results:

db.collection_name.find( { name: "soumik" } ). sort( { "age" : 1 } )

It will show result with people whose name is "soumik" and result will be sorted in ascending order based on age.

To sort result in descending order, instead of 1 change the value to 0 "age" : 0.

If we add more than one value inside sort() lets say, sort({ "age":1, "year": 1}) this will sort the result based on age and if both have same age, it will be sorted based on year.

Array in MongoDB

Data can be stored as an array in document too, the data representation look like this:

1{
2	_id: ObjectId("5eb3d66831de5d88f4305b"),
3	name: "Soumik",
4	age: 22
5	hobbies: ["drawing", "photography"]
6}

Exact array match:

db.collection_name.find({ hobbies: ["drawing"] })

The output of the query will be the document where someone has only "drawing" as hobbies.

1{
2	_id: ObjectId("5eb3d66831de5d88f4305b"),
3	name: "Soumik",
4	age: 22
5	hobbies: ["drawing"]
6}

Single array element match:

db.collection_name.find({ hobbies: "drawing" })

The output will show all the documents that has "drawing" as its value, it can have more one value but it must contain "drawing" in it.

1{
2	_id: ObjectId("5eb3d66831de5d88f4305b"),
3	name: "Soumik",
4	age: 22
5	hobbies: ["drawing", "photography"]
6}
7{
8	_id: ObjectId("663e1063779dd1c9a6fa6079"),
9	name: "Smik",
10	age: 22
11	hobbies: ["drawing"]
12}
13

Array operator:

$all : it will match all the query array elements inside $all with document elements.

$elemMatch : It will search for at least one array element that satisfy the condition inside $elemMatch

$in : it searches the document array for any element that matches with the query element

Here is an example using all array operator:

1db.student.find({ hobbies: { $all: ["drawing", "photography"] } })
2
3[
4  {
5    _id: ObjectId("663e1063779dd1c9a6fa6078"),
6    name: 'soumik',
7    age: 22,
8    hobbies: ['drawing', 'photography']
9  }
10]
11
12db.student.find({ hobbies: { $elemMatch: { $eq: "drawing" } } })
13
14[
15  {
16    _id: ObjectId("663e1063779dd1c9a6fa6078"),
17    name: 'soumik',
18    age: 22,
19    hobbies: ['drawing', 'photography']
20  },
21  {
22    _id: ObjectId("663e1063779dd1c9a6fa6079"),
23    name: 'smik',
24    age: 22,
25    hobbies: ['drawing']
26  }
27]
28
29db.student.find({ hobbies: { $in: ["photography", "drawing"] } })
30
31[
32  {
33    _id: ObjectId("663e1063779dd1c9a6fa6078"),
34    name: 'soumik',
35    age: 22,
36    hobbies: ['drawing', 'photography']
37  },
38  {
39    _id: ObjectId("663e1063779dd1c9a6fa6079"),
40    name: 'smik',
41    age: 22,
42    hobbies: ['drawing']
43  }
44]

Array fields with embedded documents:

The representation of this type of document is embedded documents are kept inside array documents.

1{
2	_id: ObjectId("663e1063779dd1c9a6fa6078"),
3	name: "soumik",
4	age: 22
5	hobbies: ["drawing", "photography"],
6	exp: [{
7		company: "xyz",
8		year: 2
9	},
10	{
11		company: "abc",
12		year: 3
13	}	
14	]
15}
16

Here as you can see the exp is an array embedded document where an document is embedded inside an array.

Update a Document

To update a single document we use this query:

db.collection_name.updateOne({ name: "soumik" }, {$set: {age: 91}})

filter : first we filter out our result which we will change, in our case name: "soumik"

update : then we use the $set operator then update the previous value, like $set: {age: 91}

options : we can specify some options here if we want, if we want to create a new document if it doesn't exist we can use {upsert: true}

To update many document we use this query:

db.collection_name.updateMany({ name: "soumik" }, {$set: {age: 91, name: "oldie"}})

In this case, we filtered out the result by name then we modified every document which has name: "soumik" and change the age to 91 and name to "oldie".

To update embedded document:

db.collection_name.updateOne({ name: "soumik" }, {$set: { "parent.child": 1 }})

To update array document:

db.collection_name.updateOne({ name: "soumik" }, {$set: { "exp.0.year": 1 }})

In this query we have updated embedded array's document with 0th index year value to 1.

Append new document inside embedded array document:

Let's say we want to append another document array inside embedded array document then we can use this query

db.collection_name.updateOne({name: "soumik"}, {$push: {exp: {company: "lmao", year: 9}}})

Upserting a document which mean either update or insert a document:

We will add another document and if it's not present instead of update it will insert the document in it. Let's try to add another data inside our document

db.collection_name.updateOne({name: "soumik"}, {$set: {email: "xyz12@gmail.com"}}, {upsert: true})

Modify a document

We can use the findAndModify() query to find and update document. The following query will be

db.collection_name.findAndModify({query: {name: "soumik"}, update:{age: 91}, new: true})

The query can have four parameters:

query will filter out the document that matches the query

update will contain the updated document data

new will show the new updated document after modifying

upsert will update the old document if exists else it will insert a new document

Delete a Document

To delete one single document from the collection, we use the deleteOne()

db.collection_name.deleteOne({ name: "soumik" })

To delete more than one or let's say delete document in bulk, we can use the deleteMany() query.

db.collection_name.deleteMany({ name: "soumik" })

Replace the document with new document:

It replaces existing document and inserts new document inside it.

db.collection_name.replaceOne({ name: "soumik" }, {name: "lmao", age: 91})

We can use another parameter upsert as true to insert new data if it doesn't exist.

Indexing in Document

Indexing in MongoDB works as labeling documents based on similar data. Or you can think of it as index page of a book, it separates similar data in a place so that you don't have to read/search the whole book to find the specific data.

Main purpose of indexing is to improve performance of searching a document by labeling data so that we dont have to search the whole big document.

Here is a visual representation of indexing in MongoDB:

Blog Image

We have one collection called student where student where all the students are present with age value, now we made a index where only 12 year olds are separated, so now if we want to find someone whose age is 12, we dont have search the whole student document. This might not look like a big difference but for large scale data it's efficient.

Add Index

Query to add indexing:

db.collection_name.createIndex({age: 1})

Here age: 1 means it will sort the index in ascending order, and if we write age: -1 it will sort it in descending order.

Compound Index:

db.collection_name.createIndex({age: 1, name: -1})

This will create index which will sort age in ascending order and name in descending order.

Delete Index

To delete index you can use this query:

db.collection_name.dropIndex( "age_1" )

This will delete the index which was storing the age index named age_1

Aggregation

Aggregate means to combine several filtering or sorting methods to get a result.

Aggregation pipelines:

Aggregation pipeline is like sending document from end of pipe to other end but inside pipe there are segments each segment performs certain operations on the pipe like sorting or filtering data.

To use aggregate using pipelines we have to use the .aggregate() method

db.collecion_name.aggregate()

Match our result in a stage:

As we came to know there are many stages in a pipeline, there is a simple $match method which works as .find() method.

db.collection_name.aggregate([ { $match: {name: "soumik"} } ])

Sort our results on next stage:

db.collection_name.aggregate([ { $match: {name: "soumik"} }, { $sort: {age: 1} } ])

We can also add new fields in our document using$addFields:

db.collection_name.aggregate([ { $match: {name: "soumik"}}, { $addFields: {totalExp: {$sum: { "$exp.year" }}}} ])

This will add a new field called totalExp to our document which will add the years inside exp.year and sum it up.

Create new collection using $out method:

db.collection_name.aggregate([ { $match: {age: 22}}, {$out: "age_22"} ])

It will make a new collection in our database which matches the age 22 and create a new collection storing document who is 22 years old.