MongoDB is the world's most popular NoSQL document database. Instead of storing data in rows and columns like SQL, MongoDB stores data as flexible JSON-like documents. This lesson covers the core concepts, installation, and your first steps with the MongoDB shell.
Traditional relational databases (MySQL, PostgreSQL) store data in structured tables with fixed schemas. MongoDB takes a fundamentally different approach — data lives in documents inside collections.
| Concept | SQL (Relational) | MongoDB (Document) |
|---|---|---|
| Data unit | Row / Record | Document (BSON/JSON) |
| Grouping | Table | Collection |
| Database | Database | Database |
| Schema | Fixed — ALTER TABLE required | Flexible — each doc can differ |
| Relationships | Foreign keys + JOINs | Embedding or $lookup |
| Scaling | Vertical (bigger server) | Horizontal (sharding) |
| Query language | SQL | MongoDB Query Language (MQL) |
| Transactions | ACID by default | ACID since v4.0 (multi-doc) |
| Best for | Structured, relational data | Flexible, hierarchical, high-volume |
| Examples | MySQL, PostgreSQL, SQLite | MongoDB, CouchDB, Firestore |
A document is a JSON-like object (stored as BSON internally). It is the basic unit of data in MongoDB, equivalent to a row in SQL — but far more flexible.
// A MongoDB document — a user record { "_id": ObjectId("64a1b2c3d4e5f60718293a4b"), "name": "Alice Johnson", "email": "alice@example.com", "age": 29, "active": true, "tags": ["admin", "editor"], "address": { "city": "New York", "zip": "10001" }, "createdAt": ISODate("2024-01-15T09:30:00Z") }
A collection is a group of documents — like a SQL table, but without an enforced schema. Documents in the same collection can have different fields.
A MongoDB server can host multiple databases. Each database has its own collections. Common databases: myapp, test, admin, local.
Every document must have a unique _id field. If you don't provide one, MongoDB auto-generates an ObjectId — a 12-byte BSON type that encodes timestamp + machine + process + counter. This guarantees global uniqueness without a central authority.
// ObjectId structure (12 bytes) ObjectId("64a1b2c3 d4e5 f607 182 93a4b") // ^------^ ^--^ ^--^ ^--^ ^---^ // 4b time 3b 2b 1b 3b // mac pid inc counter // Extract the timestamp from an ObjectId: ObjectId("64a1b2c3d4e5f60718293a4b").getTimestamp() // ISODate("2023-07-02T12:00:00Z")
MongoDB stores documents as BSON — a binary-encoded format that extends JSON with additional types:
| BSON Type | Description | Example |
|---|---|---|
| Double | 64-bit float | 3.14 |
| String | UTF-8 string | "hello" |
| Object | Embedded document | { key: val } |
| Array | List of values | [1, 2, 3] |
| ObjectId | 12-byte unique ID | ObjectId("...") |
| Boolean | true / false | true |
| Date | 64-bit UTC milliseconds | ISODate("2024-01-01") |
| Null | Null value | null |
| Int32 / Int64 | Integer types | 42 |
| Decimal128 | High-precision decimal | NumberDecimal("9.99") |
| Binary | Raw binary data | Images, files |
| Regex | Regular expression | /pattern/flags |
# Import MongoDB public GPG key curl -fsSL https://pgp.mongodb.com/server-7.0.asc | \ sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor # Add MongoDB repository echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] \ https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \ sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list # Install MongoDB sudo apt-get update sudo apt-get install -y mongodb-org # Start and enable the service sudo systemctl start mongod sudo systemctl enable mongod # Verify it's running sudo systemctl status mongod
# Tap the MongoDB formula repository brew tap mongodb/brew # Install MongoDB Community Edition brew install mongodb-community@7.0 # Start MongoDB as a background service brew services start mongodb-community@7.0 # Or run it manually (foreground) mongod --config /usr/local/etc/mongod.conf
# 1. Download the MSI from: # https://www.mongodb.com/try/download/community # Select: Version 7.0, Platform: Windows, Package: msi # 2. Run the installer # - Choose "Complete" installation # - Check "Install MongoDB as a Service" # - Default data path: C:\data\db # - Default log path: C:\data\log\mongod.log # 3. mongod is now in: C:\Program Files\MongoDB\Server\7.0\bin\ # 4. Add it to your PATH environment variable # 5. Start the service (if not auto-started) net start MongoDB # 6. Stop the service net stop MongoDB
# Ubuntu sudo apt-get install -y mongosh # macOS brew install mongosh # Windows — download from: # https://www.mongodb.com/try/download/shell # Or via npm (all platforms) npm install -g mongosh
# Connect to local MongoDB (default port 27017) mongosh # Connect to a specific host and port mongosh "mongodb://localhost:27017" # Connect with authentication mongosh "mongodb://username:password@localhost:27017/mydb" # Connect to MongoDB Atlas mongosh "mongodb+srv://user:pass@cluster0.abcde.mongodb.net/mydb"
// Show all databases show dbs // Switch to (or create) a database use myapp // Show current database name db // Show all collections in current database show collections // Show all users in current database show users // Drop the current database db.dropDatabase() // Get database stats db.stats() // Get collection stats db.users.stats() // Show server status db.serverStatus()
MongoDB Atlas is the fully managed cloud database service. The free tier (M0) gives you 512MB of storage — perfect for learning and small projects.
Cluster0)0.0.0.0/0 for any IP)# Your Atlas connection string looks like: mongosh "mongodb+srv://myUser:myPassword@cluster0.abcde.mongodb.net/" # Store it as an environment variable (never hardcode passwords) export MONGODB_URI="mongodb+srv://myUser:myPassword@cluster0.abcde.mongodb.net/" mongosh "$MONGODB_URI"
// Switch to a new database (created lazily on first write) use learnmongo // Insert a single document into the "users" collection db.users.insertOne({ name: "Bob Smith", email: "bob@example.com", age: 32, skills: ["JavaScript", "Python"], joinedAt: new Date() }) // Output: // { // acknowledged: true, // insertedId: ObjectId("64a1b2c3d4e5f60718293a4b") // } // Insert multiple documents at once db.users.insertMany([ { name: "Carol White", email: "carol@example.com", age: 25 }, { name: "Dave Brown", email: "dave@example.com", age: 41 } ]) // Find ALL documents in the collection db.users.find() // Find with a filter (age greater than 30) db.users.find({ age: { $gt: 30 } }) // Find ONE document by email db.users.findOne({ email: "bob@example.com" }) // Find and project only name and email (hide _id) db.users.find({}, { name: 1, email: 1, _id: 0 })
// Count all documents db.users.countDocuments() // Count with a filter db.users.countDocuments({ age: { $gte: 30 } }) // Sort by age ascending (1) or descending (-1) db.users.find().sort({ age: 1 }) db.users.find().sort({ age: -1 }) // Chain: filter + sort + limit + skip db.users.find({ active: true }) .sort({ name: 1 }) .skip(10) .limit(5)
| Command | Description |
|---|---|
show dbs | List all databases |
use <dbname> | Switch to / create a database |
db | Show current database name |
show collections | List collections in current database |
db.<col>.insertOne({}) | Insert a single document |
db.<col>.insertMany([]) | Insert multiple documents |
db.<col>.find() | Return all documents (cursor) |
db.<col>.findOne({}) | Return first matching document |
db.<col>.find({}).sort() | Sort results |
db.<col>.find({}).limit(n) | Limit number of results |
db.<col>.find({}).skip(n) | Skip first n results |
db.<col>.countDocuments({}) | Count matching documents |
db.<col>.updateOne({}, {$set:{}}) | Update first matching doc |
db.<col>.updateMany({}, {$set:{}}) | Update all matching docs |
db.<col>.deleteOne({}) | Delete first matching doc |
db.<col>.deleteMany({}) | Delete all matching docs |
db.<col>.drop() | Drop (delete) the entire collection |
db.dropDatabase() | Drop the current database |
db.<col>.createIndex({}) | Create an index |
db.<col>.getIndexes() | List all indexes on a collection |
db.<col>.explain().find({}) | Show query execution plan |
db.<col>.aggregate([]) | Run aggregation pipeline |
exit or quit() | Exit the shell |
cls | Clear the terminal screen |
it | Iterate through cursor results |
// Step 1: Start the shell and create a database use bookstore // Step 2: Insert some books db.books.insertMany([ { title: "The Pragmatic Programmer", author: "Andrew Hunt", year: 1999, price: 49.99, tags: ["programming", "software"], inStock: true }, { title: "Clean Code", author: "Robert C. Martin", year: 2008, price: 39.99, tags: ["programming", "best practices"], inStock: true }, { title: "Designing Data-Intensive Applications", author: "Martin Kleppmann", year: 2017, price: 59.99, tags: ["databases", "distributed systems"], inStock: false } ]) // Step 3: Find books in stock db.books.find({ inStock: true }) // Step 4: Find books under $50, sorted by year db.books.find({ price: { $lt: 50 } }).sort({ year: 1 }) // Step 5: Count books with "programming" tag db.books.countDocuments({ tags: "programming" }) // Step 6: Show only title and price db.books.find({}, { title: 1, price: 1, _id: 0 })