Skip to main content

Intro to MongoDB

Learning Objectives

Students Will Be Able To:
Describe the Use Case of Databases
Describe the Format of a Document
Save and Retrieve MongoDB Documents using the Mongo Shell
Describe Embedding & Referencing

Road Map

  • What's a Database?
  • MongoDB vs. Relational SQL Databases
  • More About MongoDB
  • MongoDB Documents
  • Creating a Database and Inserting Documents
  • Data Modeling - Intro
  • Data Modeling in MongoDB

Videos

Video 📹 Link

What's a Database?

Remember when we added new To-Dos in Express and we would "lose" them when nodemon restarted the server?

If we were saving those To-Dos in a database, they would remain there until we deleted them.

Databases are a way to organize and save, or persist, data.

There are lots of different database systems - check out this site that tracks the popularity of different database systems.

As you can see, Relational Database Management Systems (RDMS) are by far the most popular - they've been around since the 1960s. They are more commonly referred to as SQL Databases because they are designed and accessed using Structured Query Language.

However, you'll also see that MongoDB is by far the most popular NoSQL database system.

There are several varieties of NoSQL databases. MongoDB is of the document-based variety because it stores and retrieves documents.

MongoDB vs. Relational SQL Databases

Terminology

As diagramed above, there is a one-to-one mapping of the key concepts of a database.

Key Differences

Use Cases

Either a SQL database or MongoDB can be used for most applications.

However, in general:

  • Relational Databases are preferred in mission-critical financial applications such as banking, stock trading, etc., due to their strength of handling transactions. They are not very good however on handling data that can't be strictly organized into tables of structured columns because they have a strict schema (structure) they must adhere to.

  • MongoDB is preferred for storing vast amounts of unstructured data, such as in social-media type applications. MongoDB is also a great choice when prototyping applications because it is schema-less and more adaptable to change.

More About MongoDB

MongoDB puts the "M" in the MEAN/MERN Stack, technology stacks that emphasizes the use of JavaScript on both the front-end and back-end.

Instead of SQL (Structured Query Language), MongoDB uses JavaScript as its native language for database operations.

You're going to see that working with data in MongoDB is like working with JavaScript objects.

MongoDB Documents

In MongoDB, we save and retrieve documents to and from a collection.

Lets take a look of what a MongoDB document might look like:

{
_id: ObjectId("5099803df3f4948bd2f98391"),
name: { first: "Alan", last: "Turing" },
birth: ISODate("1912-06-23T00:00:00Z"),
death: ISODate("1954-06-07T00:00:00Z"),
contribs: [ "Turing machine", "Turing test", "Turingery" ],
views: 1250000
}

As you can see, this format looks very much like a JavaScript object.

In fact, you'll be working with documents using JavaScript, therefore they absolutely are JS objects!

The Document _id

The _id is a special field that represents the document's unique identifier. If you're familiar with SQL databases, a document's _id is like a primary key.

MongoDB automatically creates the _id when documents are saved for the first time.

MongoDB uses a special ObjectId datatype for the value of _id.

note

ObjectIds are JS objects, but we'll be able to use their string representation most of the time when we work with them in Mongoose (next lesson).

The value that MongoDB creates for the _id is guaranteed to be globally unique.

Creating a Database and Inserting Documents

Before we Start

In this lesson, we are going to be working directly with MongoDB to create and read data using the MongoDB Shell in a Terminal window.

However, after this brief session working with the MongoDB Shell, you will likely never do it again since most developers use the Mongoose library to CRUD a MongoDB. We're going to learn Mongoose next!

The MongoDB Shell

Below repeats how to connect to the MongoDB Shell that we saw in the previous Create an Atlas Hosted MongoDB lesson...

Click the Connect button again and this time select Connect with the MongoDB Shell:

Although Atlas may show how to permanently install mongosh (MongoDB's Shell) for your operating system. It is not necessary to do so.

Instead, we can temporarily install and run mongosh by copying and pasting the command shown in Atlas into Terminal. Be sure to replace <username> with your username that you created earlier.

❗️ Before pressing enter, add npx to the front of the command so that the command looks something like this:

npx mongosh "mongodb+srv://cluster0.oynsb.azure.mongodb.net/myFirstDatabase" --apiVersion 1 --username yourusername

If prompted to install, be sure to answer with y.

You will be prompted to enter your database user's password.

You should now be in the shell and see a prompt similar to the following:

Atlas atlas-lge6ib-shard-0 [primary] myFirstDatabase>

List the shell's commands available: > help

Show the list of databases: > show dbs

note

Note that myFirstDatabase will not be in the list until we create our first document.

Show the name of the currently active database: > db

Show the collections of the current database > show collections

Inserting Documents into a Collection

This is how we can create and insert a document into a collection named people:

// Be sure not to type the "..."s below
// they simply indicate multi-line input mode
> db.people.insertOne({
... name: 'Maria',
... favColor: 'Orange'
})

Using a collection for the first time creates it!

> show collections
people

👉 YOU DO - Add Another Document (1 min)

  • Add another "person" document to the db.people collection. But this time, add an additional field called birthDate and assign it a date value with something like this: birthDate: new Date('3/21/1981')

Reading Documents in a Collection

We can list the documents in the collection using the find() method on the collection:

> db.people.find({})
[
{
_id: ObjectId("633c9f214c88975587bfa14d"),
name: 'Maria',
color: 'Orange'
},
{
_id: ObjectId("633c9f214c88975587bfa14e"),
name: 'Jim',
color: 'Purple',
birthDate: ISODate("2001-06-13T07:00:00.000Z")
}
]

The {} argument is called a query object and is used to specify the criteria of the query. If we provide an empty query object, i.e., find({}), all documents in the collection are returned.

Here's how we can find "person" documents with the best color:

db.people.find({color: 'Purple'})
[
{
_id: ObjectId("633c9f214c88975587bfa14e"),
name: 'Jim',
color: 'Purple',
birthDate: ISODate("2001-06-13T07:00:00.000Z")
}
]

Exit the MongoDB Shell

Type exit or quit to exit the shell.

Data Modeling - Intro

Data Entities

A Data Entity is to data modeling as a Data Resource is to RESTful Routing/CRUD.

A data entity represents a type of data in an application.

Examples include: User, Account, Post, Comment, etc.

Relationships

Relationships exist between entities, for example:

  • A User has many Posts; and a Post belongs to a User
    This relationship is called a one-to-many.
  • A User has and belongs to many Accounts; and an Account has and belongs to many Users
    This relationship is called a many-to-many.

There is also a less common one-to-one relationship. For example, A User has a Profile; and a Profile belongs to a User

You will be asked to model the relationships as part the planning for your CRUD projects. Here's a link that talks more about data relationships and how to create what's called an Entity Relationship Diagram (ERD).

Database Implementation

SQL Databases

In SQL Databases, by design, there would be a table for each data entity.

Related data is joined together using SQL queries.

MongoDB

In MongoDB, unlike with SQL tables, there might not be a collection for every data entity.

Unlike in SQL, there's no requirement to break different entity types into separate collections.

The reason is that some entities are better off being embedded with its parent document instead, for example, comments that belong to a post. It would not make sense to have to query a separate comments collection to obtain the comments for a given post...

Data Modeling in MongoDB

There are two ways to model related data in MongoDB:

  1. Using embedding, where "subdocuments" are contained inside of its document.

  2. Using referencing, where a document contains just the related document's ObjectId.

Both approaches can be used simultaneously in the same document.

Embedded Documents

Here's what an embedding looks like:

A document in the people collection:

// assume a document from a people collection
{
_id: ObjectId("5099803df3f4948bd2e983a4"),
name: "Joe Smith",
contacts: [
{
type: "mobile",
contact: "(555) 555-5555"
},
{
type: "email",
contact: "joe@smith.com"
}
]
}

In a relational database, those contacts would have to be in a separate table.

Embedding data is more efficient than referencing data because it takes extra queries to fetch related data.

FYI, when we use Mongoose, even those subdocuments will automatically have their own _id.

Referencing Documents (linking)

Here's how the above person --< contact model would be implemented via referencing:

// assume a document from a people collection
{
_id: ObjectId("5099803df3f4948bd2e983a4"),
name: "Joe Smith",
contacts: [
ObjectId("5099803df3f4948bd2f98391"),
ObjectId("5099803df3f4948bd1f97203")
]
}

Two referenced documents in the contacts collection:

{
_id: ObjectId("5099803df3f4948bd2f98391"),
type: "mobile",
contact: "(555) 555-5555"
}

and

{
_id: ObjectId("5099803df3f4948bd1f97203"),
type: "email",
contact: "joe@smith.com"
}

As you can see, the related contacts are separate documents.

We would have to make separate queries to get to that data, although, Mongoose can do this automatically using the populate method.

Which Document Should Hold the "Reference"?

When referencing data in MongoDB, you can hold the ObjectId in either document or both!

The decision depends upon the design and functionality of your application and it's not always clear-cut.

If Embedding is More Efficient, Why Reference at All?

  • If the amount of data can exceed the 16MB size limit for a document, an uncommon situation however - the entire body of work of Shakespeare can be stored in 5 megabytes!

  • When multiple parent documents need access the same child document and that child's data changes frequently. For example, a document modeling a bank account should be referenced because it could be "owned" by more than one individual - if the account data were embedded in two or more parent documents, can you imagine how difficult it would be keeping the transactional & balance data in sync?

  • If it makes sense for your application. For example, if you wanted to view all posts on your landing page, regardless of the user that posted them, it would certainly take more effort to extract the posts from each user if they were embedded. However, it would be gravy to get the posts from their own collection.

For more details regarding data modeling in MongoDB, start with this section of mongoDB's documentation or this hour long YouTube video

References

MongoDB homepage

MongoDB Atlas - MongoDB Cloud Hosting

MongooseJS - ODM