MongoDB is a C++-built NoSQL database focused on distributed document storage, delivering stable, high-performance, scalable data storage for web applications.
Core MongoDB Characteristics
- Schema-free: Documents with varying structures can coexist in a single collection
- Collection-oriented storage: Optimized for JSON-like BSON data formats
- Full indexing coverage: Any attribute, including nested objects/arrays, can be indexed
- Replication and high availability: Supports primary-secondary and mutual replication for redundancy and automatic failover
- Auto-sharding: Enables horizontal cloud-scale clustering with dynamic node addition
- Rich query language: Uses JSON-style syntax to filter nested structures and arrays
- Optimized in-place updates: Query optimizer generates efficient execution plans
- Efficient large/binary data handling: Natively supports media files and other binary assets
Core Data Model and Terminology
MongoDB organizes data into BSON documents, wich are key-value pairs with nested document/array support. The three-tier structure maps to relational databases as follows:
| SQL Concept | MongoDB Equivalent | Explanation |
|---|---|---|
| database | database | Container for collections |
| table | collection | Container for BSON documents |
| row | document | Individual data record |
| column | field | Key in a BSON document |
| index | index | Performence optimization structure |
| table joins | N/A | Not natively supported; use embedding or application-side lookups |
| primary key | primary key | Auto-assigned as _id; can be manually specified |
A BSON document example:
{ product: "wireless headphones", stock: 42, variants: ["black", "silver"] }
Collections, unlike relational tables, enforce no fixed schema, so mixed documents are valid:
{ product: "wireless headphones", stock: 42 }
{ user: "alex", signup_date: ISODate("2024-01-15") }
{ report_id: "2024-Q1", metrics: { downloads: 1200, revenue: 45000 } }
A single MongoDB server typically hosts multiple databases, each containing multiple collections.
Installation (Linux Ubuntu Example)
- Version Selection: Use even minor versions (e.g., 7.0.x) for stability; avoid 32-bit builds (2GB storage limit)
- Download and extract official binaries
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-7.0.9.tgz tar -xzf mongodb-linux-x86_64-ubuntu2204-7.0.9.tgz - Move to system directory
sudo mv mongodb-linux-x86_64-ubuntu2204-7.0.9 /opt/mongodb7 - Add binaries to PATH (persist in ~/.bashrc for permanent access)
echo 'export PATH=/opt/mongodb7/bin:$PATH' >> ~/.bashrc source ~/.bashrc
Server Management
- Default configuration file:
/etc/mongod.conf - Default port:
27017 - Start/stop via systemd
sudo systemctl start mongod sudo systemctl stop mongod - Connect via built-in JavaScript shell
mongosh - Basic shell utilities
db // Show current active database db.stats() // Display current database metrics - Exit the shell
exit
Database Operations
- List physical databases
show dbs - Switch/create database
use inventory_db // Creates database only after first data insertion - Delete current database
db.dropDatabase()
Collection Operations
- Create a collection
// Basic, unbounded collection db.createCollection("products") // Capped collection (fixed size, overwrites oldest entries when full) db.createCollection("activity_log", { capped: true, size: 10240 }) // 10KB limit - List collections
show collections - Delete a collection
db.products.drop()
Common BSON Data Types
ObjectId: Auto-generated 12-byte unique identifier for_idString: UTF-8 encoded textBoolean:true/falseInt32/Int64: Integer types (server-dependent)Double: Floating-point numbersArray: Ordered list of valuesObject: Nested BSON documentNull: Null valueTimestamp: Internal MongoDB timestampISODate: Date/time stored as 64-bit integer
The 12-byte ObjectId breaks down as:
- 4 bytes: Unix timestamp
- 3 bytes: Machine identifier
- 2 bytes: Process ID
- 3 bytes: Incrementing counter
Document Write Operations
- Insert documents
// Single insert db.products.insertOne({ name: "bluetooth speaker", price: 29.99, category: "audio" }) // Predefined document insert let monitor = { _id: "prod_001", name: "27-inch 4K monitor", price: 349.99, category: "display" } monitor.resolution = "3840x2160" db.products.insertOne(monitor) - Update documents
// Replace entire matching document (first match only by default) db.products.updateOne({ name: "bluetooth speaker" }, { name: "portable BT speaker", price: 24.99 }) // Update specific fields with $set db.products.updateOne({ name: "27-inch 4K monitor" }, { $set: { price: 319.99, in_stock: true } }) // Remove a field with $unset db.products.updateOne({ _id: "prod_001" }, { $unset: { resolution: "" } }) // Update all matching documents db.products.updateMany({ category: "audio" }, { $set: { discount: 0.1 } }) - Upsert (save-like operation)
db.products.updateOne( { _id: "prod_002" }, { $set: { name: "mechanical keyboard", price: 89.99, category: "input" } }, { upsert: true } ) - Delete documents
// Delete first matching document db.products.deleteOne({ category: "display" }) // Delete all matching documents db.products.deleteMany({ price: { $lt: 20 } })
Capped Collection Demonstration
- Create capped collection
db.createCollection("recent_orders", { capped: true, size: 512 }) - Insert test entries until cap is reached
db.recent_orders.insertMany([ { order_id: "ord_001", item: "mouse pad", qty: 2 }, { order_id: "ord_002", item: "USB-C cable", qty: 3 }, { order_id: "ord_003", item: "webcam", qty: 1 }, { order_id: "ord_004", item: "laptop stand", qty: 1 }, { order_id: "ord_005", item: "mouse", qty: 1 } ]) - Query to see oldest entries overwritten
db.recent_orders.find()
Document Read Operations
Basic Querying
- Find all matching documents
db.products.find({ category: "audio" }) - Find first matching document
db.products.findOne({ category: "input" }) - Format output for readability
db.products.find({ in_stock: true }).pretty()
Comparison Operators
| Operator | Description |
|---|---|
| (none) | Equals |
$lt |
Less than |
$lte |
Less than or equal |
$gt |
Greater than |
$gte |
Greater than or equal |
$ne |
Not equal |
Examples:
// Find products under $50
db.products.find({ price: { $lt: 50 } })
// Find products priced $100–$300
db.products.find({ price: { $gte: 100, $lte: 300 } })
Logical Operators
- Logical AND: Default for multiple top-level conditions
db.products.find({ category: "audio", in_stock: true }) - Logical OR: Use
$orarraydb.products.find({ $or: [{ category: "display" }, { price: { $gt: 200 } }] }) - Combined AND/OR
db.products.find({ in_stock: true, $or: [{ category: "audio" }, { category: "input" }] })
Range Operators
$in: Match any value in array$nin: Match no values in array
// Find products in audio or display categories
db.products.find({ category: { $in: ["audio", "display"] } })
Regular Expression Matching
Use /pattern/ or $regex for flexible text searches
// Find products with names starting with "portable"
db.products.find({ name: /^portable/ })
db.products.find({ name: { $regex: "^portable" } })
Custom JavaScript Filtering
Use $where with a JavaScript predicate function
// Find products where discount is at least 10% of price
db.products.find({ $where: function() { return this.discount >= this.price * 0.1; } })
Pagination
Use skip() and limit() together (order does not affect results)
// Generate 20 test documents
for(let i=1; i<=20; i++){ db.test_data.insertOne({ seq: i, label: "test_"+i }) }
// Get documents 6–10 (5 skipped, 5 returned)
db.test_data.find().skip(5).limit(5)
db.test_data.find().limit(5).skip(5)
Projection
Select only required fields in results
// Show name and price only (auto-includes _id)
db.products.find({ in_stock: true }, { name: 1, price: 1 })
// Exclude _id
db.products.find({ in_stock: true }, { _id: 0, name: 1, price: 1 })
Sorting
Sort results with sort(), using 1 for ascending, -1 for descending
// Sort by category ascending, then price descending
db.products.find().sort({ category: 1, price: -1 })
Aggregation Helpers
- Count matching documents
db.products.find({ category: "audio" }).count() db.products.countDocuments({ category: "audio" }) - Get distinct values
// Get all unique product categories db.products.distinct("category") // Get unique categories for in-stock products under $100 db.products.distinct("category", { in_stock: true, price: { $lt: 100 } })