Databases & Collections
MongoDB organizes data in a three-level hierarchy:
- MongoDB instance — a running
mongodprocess (or Atlas cluster). A single instance can host many databases. - Database — a logical namespace that groups related collections. Each database has its own set of collections, users, and permissions.
- Collection — a container for documents, analogous to a table in a relational database but without an enforced schema.
- Document — a single BSON record inside a collection. This is the fundamental unit of data in MongoDB.
This hierarchy lets you isolate data by application, environment, or tenant while keeping everything manageable from one connection.
Understanding Databases
A MongoDB deployment can host multiple databases simultaneously. Each database has its own set of collections and is completely isolated from others — a query against one database never reads or modifies documents in another. This isolation makes databases a natural boundary for different applications or environments (e.g., myapp_production, myapp_staging, analytics).
Working with databases in mongosh
// List all databases on the instance show dbs // Switch to (or prepare to create) a database use myDatabase // Note: the database is NOT created until you write the first document // Check which database you are currently on db.getName() // returns "myDatabase" // Get database statistics: size, collection count, index count db.stats() // Drop the entire database (all collections and data — irreversible) db.dropDatabase()
System Databases
Every MongoDB deployment ships with three built-in system databases. They are essential to MongoDB's operation and must never be dropped or modified directly.
admin — the root database. Users created here can have cluster-wide privileges. Authentication, role management, and administrative commands (shutdownServer, listDatabases) run against this database.
local — exists on every mongod instance and is never replicated. Stores the replication oplog, startup log, and other instance-local data.
config — used by sharded clusters to store metadata about each shard, chunk ranges, and balancer settings. Never modify this directly.
admin, local, or config databases. Doing so can permanently break authentication, replication, or sharding.Understanding Collections
A collection is a group of MongoDB documents — roughly analogous to a table in a relational database, but with no enforced schema by default. Documents within a collection can have completely different fields and data types, giving you the flexibility to evolve your data model over time.
That said, storing structurally similar documents in the same collection is a strong convention: it keeps queries fast, indexes small, and code predictable.
Creating and managing collections
// Explicitly create a collection (optional — see implicit creation below)
db.createCollection("users")
// List all collections in the current database
show collections
// Also available as:
db.getCollectionNames()
// Drop a collection (all documents and indexes — irreversible)
db.users.drop()Implicit vs Explicit Creation
MongoDB supports two ways to bring a collection into existence:
Implicit creation — MongoDB automatically creates a collection the first time you insert a document into it. This is the most common workflow during development:
// "logs" collection is created automatically on first insert
db.logs.insertOne({ level: "info", message: "Server started", ts: new Date() })
Explicit creation — use db.createCollection() when you need to set collection-level options upfront: capped size, document validation, collation, or storage engine settings. You cannot change some of these options after creation.
createCollection Options
Option | Type | Description |
|---|---|---|
capped | Boolean | If true, creates a fixed-size collection that automatically overwrites the oldest documents when full. |
size | Number | Maximum size in bytes for a capped collection. Required when capped is true. |
max | Number | Maximum number of documents allowed in a capped collection (optional upper bound). |
validator | Object | A JSON Schema (or query expression) that documents must satisfy before insert or update. |
validationAction | String | "error" (default) rejects invalid documents; "warn" allows them but logs a warning. |
validationLevel | String | "strict" (default) validates all inserts and updates; "moderate" skips existing documents on update. |
collation | Object | Default collation for string comparison operations (language, case sensitivity, accent handling). |
Capped collection
// A capped collection keeps only the latest 1 000 log entries,
// with a hard cap of 10 MB. Oldest documents are auto-evicted.
db.createCollection("auditLog", {
capped: true,
size: 10_000_000, // 10 MB maximum
max: 1_000 // also cap by document count
})Collection with schema validation
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email", "createdAt"],
properties: {
name: {
bsonType: "string",
description: "must be a string and is required"
},
email: {
bsonType: "string",
pattern: "^.+@.+\..+$",
description: "must be a valid email address"
},
age: {
bsonType: "int",
minimum: 0,
maximum: 150,
description: "must be an integer between 0 and 150 if provided"
},
createdAt: {
bsonType: "date",
description: "must be a date and is required"
}
}
}
},
validationAction: "error", // reject documents that fail validation
validationLevel: "strict" // validate all inserts and updates
})Listing Collection Info
// Array of collection name strings
db.getCollectionNames()
// [ 'users', 'orders', 'products', 'auditLog' ]
// Detailed info: name, type, options, idIndex for each collection
db.getCollectionInfos()
// Filter by name pattern
db.getCollectionInfos({ name: "users" })
// Storage statistics for a specific collection
// (size, count, avgObjSize, storageSize, nindexes, totalIndexSize)
db.users.stats()
// Human-readable version with scale factor
db.users.stats({ scale: 1024 }) // sizes reported in KBRenaming a Collection
You can rename a collection within the same database using renameCollection(). The operation is atomic and preserves all documents and indexes.
// Rename "oldName" to "newName" within the current database
db.oldName.renameCollection("newName")
// Rename to a collection in a different database (dropTarget removes existing)
db.oldName.renameCollection("otherDb.newName", /* dropTarget */ true)show dbs and show collections only after the first document is inserted. Until then, the namespace exists only in memory (if you called use or createCollection) or not at all.db.getName() before any destructive operation.users, orders, products) — it is a well-established MongoDB community convention that makes queries read naturally: db.users.find(), db.orders.insertOne().