1. Why MongoDB? Documents vs. Rows
A relational database (like the SQL you'd use elsewhere) stores data in rigid rows with a fixed set of columns, defined up front. MongoDB stores documents — JSON-like objects that can nest arrays and other objects directly inside them, and don't require every document in a collection to share the exact same shape.
{
"_id": ObjectId("64f1a2b3c4d5e6f7a8b9c0d1"),
"name": "Asha Rao",
"email": "asha@example.com",
"tags": ["premium", "newsletter"],
"address": {
"city": "Kolkata",
"state": "West Bengal"
}
}
That nested address object and the tags array would
each need a separate, joined table in a relational database. Here, a single
document holds the whole related shape in one place — which is exactly why
document databases are such a natural fit for data that's naturally
hierarchical: user profiles, product catalogs, content management, event logs.
MongoDB doesn't enforce a schema at the database level by default, but every well-run application still has a consistent shape for its documents — it's just enforced in your application code (or with optional schema validation, covered in Week 3) instead of by the database engine itself.
2. Installing MongoDB & Connecting with mongosh
Install MongoDB Community Server locally, or skip local installation entirely and
use a free MongoDB Atlas cluster in the cloud — either works for this course.
mongosh is the official shell you'll use to run every command below.
# macOS (Homebrew)
brew tap mongodb/brew
brew install mongodb-community mongosh
# Ubuntu/Debian -- follow MongoDB's official apt instructions for your version
# Windows -- install the MSI from mongodb.com/try/download/community
# Start the server (if running locally)
mongod --dbpath /path/to/your/data/directory
# In a separate terminal, connect with the shell
mongosh
# Current Mongosh Log ID: ...
# Connecting to: mongodb://127.0.0.1:27017/
# Using MongoDB: 7.0.x
Once connected, mongosh is a full JavaScript environment — every
command in this lesson is really a JavaScript method call on a database or
collection object.
3. Databases, Collections & Documents
A MongoDB server hosts multiple databases. Each database holds collections (the rough equivalent of a table). Each collection holds documents (the rough equivalent of a row).
// Switch to (or create) a database -- it's created on first write, not on this command
use school
// List every database that actually has data
show dbs
// List collections in the current database
show collections
// Explicitly create a collection (usually unnecessary -- insertOne does this automatically)
db.createCollection("students")
show dbs once it has data
use school switches your session's context to that database name, but MongoDB doesn't actually create it on disk until you insert at least one document into a collection inside it. Running use alone is never enough to "create" a database.
4. CRUD Operations: The Five You'll Use Constantly
Every one of MongoDB's dozens of methods is a variation on five core operations. Learn these five well and you can already do real work.
// CREATE -- insert one document
db.students.insertOne({ name: "Ben Diaz", grade: 9, gpa: 3.4 })
// CREATE -- insert many documents at once
db.students.insertMany([
{ name: "Chen Wei", grade: 10, gpa: 3.9 },
{ name: "Dev Patel", grade: 9, gpa: 2.8 }
])
// READ -- find every document
db.students.find()
// READ -- find with a filter, pretty-printed
db.students.find({ grade: 9 }).pretty()
// READ -- find exactly one document
db.students.findOne({ name: "Ben Diaz" })
// UPDATE -- modify one matching document
db.students.updateOne(
{ name: "Ben Diaz" },
{ $set: { gpa: 3.5 } }
)
// UPDATE -- modify every matching document
db.students.updateMany(
{ grade: 9 },
{ $set: { onProbation: false } }
)
// DELETE -- remove one matching document
db.students.deleteOne({ name: "Dev Patel" })
// DELETE -- remove every matching document
db.students.deleteMany({ grade: 9 })
$set — don't skip it
Passing a plain object as the second argument to updateOne (without $set) replaces the entire document with just that object, silently dropping every other field. $set tells MongoDB to update only the named fields and leave the rest alone.
5. The _id Field & BSON Types
Every document gets an _id field automatically if you don't provide
one — it's the primary key, and it's required and unique within a collection.
By default MongoDB generates an ObjectId: a 12-byte value that
encodes a timestamp, so IDs are roughly sortable by creation time even without
a separate date field.
db.students.insertOne({ name: "Eva Kim", grade: 11 })
// { acknowledged: true, insertedId: ObjectId("64f...") }
// You can supply your own _id instead, if it's meaningful in your domain
db.students.insertOne({ _id: "student-eva-kim", name: "Eva Kim", grade: 11 })
// Extract the creation time embedded in a default ObjectId
db.students.findOne({ name: "Eva Kim" })._id.getTimestamp()
Under the hood, MongoDB stores documents as BSON (Binary JSON) —
a binary format that adds types plain JSON doesn't have, including
ObjectId, native Date, and distinct integer/decimal
number types. This is why a MongoDB document looks almost exactly like JSON but
isn't literally JSON on disk.
6. Hands-on Exercise
Build and manage a small library collection
Practice all five CRUD operations against data you design yourself.
Requirements:
- Connect with
mongoshanduse libraryto switch to a new database. - Use
insertManyto add at least 5 books, each withtitle,author,year,available(boolean) and agenresarray field. - Write a
findquery returning only books whereavailableistrue. - Use
updateOnewith$setto mark one book as checked out (available: false) — without overwriting its other fields. - Use
updateManyto add a new field,lastAudited: true, to every book at once. - Use
deleteOneto remove exactly one book, then confirm withfind()that only that one is gone. - Run
findOneon any book and call.getTimestamp()on its_idto confirm it matches roughly when you inserted it.
If a book's other fields vanish after your updateOne, double check you used { $set: { available: false } } and not a bare { available: false } — the latter replaces the whole document.
7. Knowledge Check
Four quick questions. Expand each to check your answer.
Q1
What is the rough MongoDB equivalent of a row in a relational table?
What is the rough MongoDB equivalent of a row in a relational table?
A document. Unlike a row, a document can nest arrays and objects directly inside it, and documents within the same collection aren't required to share an identical set of fields.
Q2
Why does running just use school not make the database appear in show dbs?
Why does running just use school not make the database appear in show dbs?
use only switches your shell session's current database context — it doesn't write anything to disk. MongoDB only actually creates the database once you insert at least one document into a collection within it.
Q3
What goes wrong if you call updateOne({ name: "Ben" }, { gpa: 3.5 }) without $set?
What goes wrong if you call updateOne({ name: "Ben" }, { gpa: 3.5 }) without $set?
Without $set, the second argument is treated as a full replacement document, not a partial update. The matched document gets entirely replaced with { gpa: 3.5 }, silently losing every other field it had — including its name.
Q4
What information is encoded inside a default MongoDB ObjectId?
What information is encoded inside a default MongoDB ObjectId?
A creation timestamp, among other components (a random value and a counter). That's why ObjectId values are roughly sortable by insertion time, and why calling .getTimestamp() on one returns a real date without the document needing its own separate date field.