Here’s a comprehensive example that covers many common MongoDB features (Quick Setup). I'll showcase operations like document creation, querying, indexing, aggregation, and more, based on a hypothetical e-commerce database structure.
Use Case: E-Commerce Database
We will use a database called ecommerce
, which contains collections like users
, products
, orders
, and reviews
.
1. Database Setup
use ecommerce;
This switches to (or creates) the ecommerce
database.
2. Inserting Documents (CRUD)
Insert Single Document
db.users.insertOne({ username: "johndoe", email: "johndoe@example.com", password: "hashed_password", createdAt: new Date()
});
Insert Multiple Documents
db.products.insertMany([ { name: "Laptop", description: "A high-end gaming laptop.", price: 1500, stock: 30, categories: ["electronics", "gaming"], ratings: [] }, { name: "Smartphone", description: "A latest model smartphone.", price: 800, stock: 50, categories: ["electronics", "mobile"], ratings: [] }
]);
3. Querying Documents
Find All Documents
db.products.find({});
Find with Conditions
db.products.find({ price: { $gt: 1000 }, categories: "electronics"
});
Find Specific Fields (Projections)
db.products.find( { price: { $gt: 1000 } }, { name: 1, price: 1, _id: 0 }
);
Sorting and Limiting Results
db.products.find().sort({ price: -1 }).limit(5);
4. Updating Documents
Update a Single Document
db.products.updateOne( { name: "Laptop" }, { $set: { price: 1400 } }
);
Update Multiple Documents
db.products.updateMany( { categories: "electronics" }, { $inc: { stock: 10 } }
);
Upsert (Update or Insert)
db.products.updateOne( { name: "Tablet" }, { $set: { name: "Tablet", description: "A lightweight tablet.", price: 500, stock: 20, categories: ["electronics", "tablet"] } }, { upsert: true }
);
5. Deleting Documents
Delete a Single Document
db.products.deleteOne({ name: "Smartphone" });
Delete Multiple Documents
db.products.deleteMany({ categories: "gaming" });
6. Indexes
Indexes are critical for performance optimization.
Create Indexes
db.products.createIndex({ name: 1 }); // Ascending index on the `name` field
db.products.createIndex({ price: -1 }); // Descending index on the `price` field
Compound Index
db.products.createIndex({ name: 1, price: -1 });
Text Index (For Full-Text Search)
db.products.createIndex({ description: "text", name: "text" });
7. Full-Text Search
Using the text index created earlier, you can perform full-text searches.
db.products.find({ $text: { $search: "gaming laptop" } });
8. Aggregation Framework
Aggregation is powerful for transforming and analyzing data.
Example: Calculate the Average Price of Products
db.products.aggregate([ { $group: { _id: null, averagePrice: { $avg: "$price" } } }
]);
Example: Products by Category
db.products.aggregate([ { $unwind: "$categories" }, { $group: { _id: "$categories", totalProducts: { $sum: 1 }, avgPrice: { $avg: "$price" } } }, { $sort: { totalProducts: -1 } }
]);
Example: Join Collections (Using $lookup
)
db.orders.aggregate([ { $lookup: { from: "users", localField: "user_id", foreignField: "_id", as: "user_details" } }
]);
9. Transactions
Starting with MongoDB 4.0, multi-document transactions are supported for replica sets.
const session = db.getMongo().startSession();
session.startTransaction(); try { db.products.updateOne( { name: "Laptop" }, { $inc: { stock: -1 } }, { session } ); db.orders.insertOne( { product_id: ObjectId("..."), user_id: ObjectId("..."), quantity: 1, totalPrice: 1500, createdAt: new Date() }, { session } ); session.commitTransaction();
} catch (e) { session.abortTransaction();
} finally { session.endSession();
}
10. Geospatial Queries
If your data includes geographical coordinates, you can perform spatial queries.
Create a Geospatial Index
db.stores.createIndex({ location: "2dsphere" });
Find Stores Near a Coordinate
db.stores.find({ location: { $near: { $geometry: { type: "Point", coordinates: [-73.97, 40.77] }, $maxDistance: 5000 // meters } }
});
11. Handling Large Documents (GridFS)
For storing large files like images or videos, MongoDB provides GridFS. Here's how you can interact with it:
Storing a File in GridFS
var bucket = new mongoose.mongo.GridFSBucket(db, { bucketName: 'myFiles'
});
bucket.openUploadStream("myImage.jpg").end("image_binary_data");
Reading a File from GridFS
bucket.openDownloadStreamByName("myImage.jpg").pipe(fs.createWriteStream("./myImage.jpg"));
12. Schema Validation
You can enforce some schema validation rules on your collections.
Example: Enforce Price to Be a Positive Number
db.createCollection("products", { validator: { $jsonSchema: { bsonType: "object", required: ["name", "price", "stock"], properties: { price: { bsonType: "double", minimum: 0, description: "Price must be a positive number" }, stock: { bsonType: "int", minimum: 0, description: "Stock must be a non-negative integer" } } } }
});
13. Role-Based Access Control (RBAC)
MongoDB supports fine-grained control over database user permissions.
Create a User with Read-Only Access to the ecommerce
Database
db.createUser({ user: "readonly_user", pwd: "password", roles: [{ role: "read", db: "ecommerce" }]
});
Create a User with Full Access
db.createUser({ user: "admin_user", pwd: "securepassword", roles: [{ role: "dbOwner", db: "ecommerce" }]
});
14. Sharding (For Scalability)
MongoDB allows horizontal scaling through sharding. This example assumes a sharded cluster is already set up.
Enable Sharding on a Database
sh.enableSharding("ecommerce");
Shard a Collection
sh.shardCollection("ecommerce.products", { product_id: "hashed" });
15. Explain
Command
The explain
command is used to understand how MongoDB processes queries. It provides insights into the query plan, index usage, and performance metrics
Example: Using explain
for Query Optimization
db.products.find({ price: { $gt: 1000 } }).explain("executionStats");
This will return detailed statistics on how the query is executed, including whether an index was used, the number of documents examined, and the time taken.
16. Change Streams
MongoDB supports Change Streams, which allow applications to listen for real-time changes to a collection, database, or even across an entire cluster.
Example: Watching Changes in a Collection
const changeStream = db.products.watch();
changeStream.on("change", (next) => { console.log("Change detected:", next);
});
This is particularly useful for real-time applications where you need to monitor data updates.
17. TTL Index (Time to Live)
TTL indexes allow you to automatically remove documents after a certain period.
Example: Set a TTL Index for Expiring Documents
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });
In this case, any document in the sessions
collection will be automatically removed 1 hour (3600 seconds) after its createdAt
timestamp.
18. Partial Indexes
Partial indexes are useful when you want to index a subset of documents in a collection, improving performance and reducing storage costs.
Example: Create a Partial Index
db.products.createIndex({ price: 1 }, { partialFilterExpression: { price: { $gt: 1000 } } });
This index will only be created for products with a price greater than 1000.
19. WildCard Indexes
WildCard indexes can be used when you need to create an index on all fields of a document, useful for semi-structured data.
Example: Create a WildCard Index
db.products.createIndex({ "$**": 1 });
This will index all fields and subfields of documents in the products
collection.
20. Hidden Indexes
Hidden indexes allow you to create indexes that MongoDB does not automatically consider during query execution, useful for testing purposes.
Example: Create and Hide an Index
db.products.createIndex({ name: 1 }, { hidden: true });
This creates an index on name
, but MongoDB will not use it for queries unless explicitly told.
21. Collations (for String Comparisons)
Collations allow you to specify language-specific rules for string comparisons, such as case-sensitivity and accent marks.
Example: Create a Collection with Case-Insensitive Collation
db.products.createIndex({ name: 1 }, { collation: { locale: "en", strength: 2 } });
This makes the name
field in the index case-insensitive for English.
22. Field-Level Encryption (FLE)
MongoDB supports Field-Level Encryption (FLE), allowing sensitive data to be encrypted at the field level.
Example: Encrypting a Field
const encryptedField = clientEncryption.encrypt("sensitive_data", { keyId: encryptionKeyId, algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
}); db.users.insertOne({ name: "John Doe", email: "johndoe@example.com", password: encryptedField
});
23. Replication
While sharding focuses on horizontal scaling, replication is designed for fault tolerance and high availability. MongoDB supports automatic failover with replica sets.
Example: Initiating a Replica Set
rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "localhost:27017" }, { _id: 1, host: "localhost:27018" }, { _id: 2, host: "localhost:27019" } ]
});
24. Concurrency Control (Optimistic Locking)
MongoDB doesn’t lock records like relational databases but allows for optimistic concurrency control via the use of a version
field (for example).
Example: Optimistic Locking with version
Field
db.orders.updateOne( { _id: ObjectId("..."), version: 1 }, { $set: { status: "shipped" }, $inc: { version: 1 } }
);
The update will only succeed if the document's version
is 1, preventing race conditions in concurrent updates.
25. MongoDB Atlas (Cloud Features)
MongoDB Atlas is the fully managed cloud version of MongoDB. It includes features like:
- Performance Advisor: Suggests indexes based on query patterns.
- Backup & Restore: Automated backups and point-in-time recovery.
- Global Clusters: Distribute data across multiple geographic regions for faster access.
Example: Setting Up Global Clusters in Atlas
In Atlas, you can define zones for data distribution across different regions. For example, store European users' data in the EU, and American users' data in the US.
Conclusion
This example provides a thorough introduction to many common MongoDB features:
- CRUD operations (insert, find, update, delete)
- Indexing (single-field, compound, text)
- Aggregation (grouping, joining)
- Transactions (multi-document)
- Full-text search
- Schema validation
- Geospatial queries
- GridFS for large files
- Role-based access control
- Sharding
Explain
command for query optimization.- Real-time change streams.
- TTL indexes for expiring data.
- Partial and wildcard indexes.
- Hidden indexes for testing.
- Collations for string comparisons.
- Field-level encryption for sensitive data.
- Replication for fault tolerance.
- Optimistic locking for concurrency control.
- Atlas-specific cloud features like backups and global clusters.
Each of these operations is essential for building efficient, scalable applications with MongoDB.
If you found this helpful, let me know by leaving a 👍 or a comment!, or if you think this post could help someone, feel free to share it! Thank you very much! 😃