1.2 Databases, Collections & Schema Flexibility

Key Takeaways

  • A MongoDB namespace is the fully qualified identifier formatted as <database>.<collection>, strictly limited to 255 bytes in WiredTiger.
  • System-reserved databases include `admin` (auth and cluster admin), `local` (instance-specific, non-replicated oplog), and `config` (sharded cluster metadata).
  • Polymorphic collections allow documents with heterogeneous structures to coexist, while `{ field: null }` queries match both explicit nulls and missing fields (exact null match requires `{ field: { $type: 10 } }`).
  • Capped collections are fixed-size FIFO circular buffers where document deletion (deleteOne/deleteMany) is strictly prohibited and updates cannot increase document byte size.
  • Time-Series collections optimize high-frequency temporal data streams via columnar bucketing configured with `timeField`, optional `metaField`, and `granularity`.
Last updated: September 2026

Databases, Collections & Schema Flexibility

Exam Focus: The Associate Developer Exam tests namespace boundaries (255-byte limit), reserved database semantics (admin, local, config), query differentiation between missing and explicit null fields ($exists vs $type), capped collection operational constraints (FIFO overwrites, prohibition of deletions, tailable cursors), and time-series collection parameter configuration (timeField, metaField, granularity).


Namespace Architecture & Naming Constraints

MongoDB organizes data into a three-tier hierarchy: Databases, Collections, and Documents.

A Namespace is the fully qualified identifier for a collection or index, constructed by concatenating the database name, a dot separator, and the collection name:

Namespace=database.collection\text{Namespace} = \langle\text{database}\rangle\text{.}\langle\text{collection}\rangle

The 255-Byte Namespace Limit

In the WiredTiger storage engine, the maximum allowable length for a namespace is 255 bytes. This byte count includes the database name, the dot separator, the collection name, and any internal index namespace prefixes (e.g., ecommerce_production.customer_order_records.$_id_). Exceeding 255 bytes results in namespace creation errors.

Database & Collection Naming Rules

  • Database Naming Rules:
    • Database names are case-sensitive (analyticsDB is distinct from analyticsdb).
    • Maximum length is 63 characters.
    • Cannot contain the null byte (\0), spaces, or any of the following restricted ASCII characters: /, \, ., ", *, <, >, :, |, ?, $. Cannot be empty.
  • Collection Naming Rules:
    • Collection names are case-sensitive.
    • Cannot contain the null byte (\0).
    • Cannot start with the reserved prefix system. (reserved for internal engine collections such as system.views, system.profile, system.buckets).
    • Cannot contain the $ character in general user collection names.

Reserved Databases & Internal Namespaces

MongoDB maintains several reserved system databases with specialized cluster and replication roles:

Reserved DatabaseReplication BehaviorPrimary Role & Description
adminReplicated across clusterCluster Administration & Auth: Stores system-wide user credentials, custom role definitions, authentication configurations, and cluster-wide administrative commands.
localNever replicated (Instance-local)Instance Diagnostics & Oplog: Stores data specific to that individual mongod instance. Contains oplog.rs (the replication operation log) and startup_log. Data in local is never copied to other replica set members.
configReplicated across Config ServersSharding Metadata: Stores the master routing table for sharded clusters, tracking chunk ranges, shard mappings, and cluster configuration settings.
testReplicated (if user creates it)Default scratchpad database loaded when launching mongosh without specifying a database name.

[!IMPORTANT] Critical Exam Rule: The local database is strictly non-replicated. Any collection created inside local exists only on that single physical node and will never be synchronized to secondary members.


Schema Flexibility: Polymorphism & Schema Versioning

Unlike relational databases which enforce rigid schema constraints across all rows in a table, MongoDB provides dynamic schema flexibility. Collections do not dictate document structure at the storage layer by default.

1. Polymorphic Collections

A single collection can store polymorphic documents—documents that share common root metadata but possess varying attributes, nested structures, or data types based on their specific entity sub-type. For instance, an e-commerce catalog collection can store books, apparel, and digital software side-by-side:

// Book entity in 'products' collection
db.products.insertOne({
  _id: ObjectId("66d57a01a1b2c3d4e5f60001"),
  type: "book",
  title: "Designing Data-Intensive Applications",
  isbn: "978-1449373320",
  pages: NumberInt(616)
});

// Apparel entity in the SAME 'products' collection
db.products.insertOne({
  _id: ObjectId("66d57a01a1b2c3d4e5f60002"),
  type: "apparel",
  title: "MongoDB Engineering Hoodie",
  sizes: ["M", "L", "XL"],
  material: "100% Organic Cotton"
});

2. The Schema Versioning Pattern

As applications evolve, document structures change (e.g., merging firstName and lastName into a single fullName field). Instead of running costly offline database migrations that rewrite millions of documents simultaneously, developers use the Schema Versioning Pattern:

// Legacy document (Schema Version 1)
{
  _id: ObjectId("..."),
  schema_version: 1,
  firstName: "Maya",
  lastName: "Lin"
}

// Modern document (Schema Version 2)
{
  _id: ObjectId("..."),
  schema_version: 2,
  fullName: "Maya Lin",
  contact: { email: "maya.lin@example.com" }
}

The application code handles multiple versions dynamically on read, updating documents to the latest version lazily during subsequent writes (lazy migration).


Querying Missing vs. Null Fields: $exists vs. $type

A classic trap on the MongoDB Associate Developer Exam involves querying documents with missing fields versus explicit BSON null values.

Suppose a collection users contains the following three documents:

{ _id: 1, name: "Alice", phone: "555-0199" }   // phone is populated
{ _id: 2, name: "Bob",   phone: null }         // phone explicitly set to null
{ _id: 3, name: "Carol" }                      // phone field does not exist

The { field: null } Trap

When you execute the query db.users.find({ phone: null }), MongoDB returns both Bob (_id: 2) and Carol (_id: 3). In MongoDB query semantics, { field: null } evaluates to true if the field contains an explicit null OR if the field is missing entirely from the document!

Differentiating Missing from Explicit Null

To target specific states, you must combine the $exists and $type operators:

Query ExpressionMatches phone: "555"Matches phone: nullMatches Missing phoneDescription & Target
{ phone: null }❌ NoYesYesMatches explicit nulls AND missing fields.
{ phone: { $exists: true } }YesYes❌ NoMatches any document where phone exists, even if null.
{ phone: { $exists: false } }❌ No❌ NoYesMatches ONLY documents where phone is absent.
{ phone: { $type: 10 } }❌ NoYes❌ NoMatches ONLY documents with explicit BSON null (Type 10).
{ phone: { $type: "null" } }❌ NoYes❌ NoAlias equivalent to Type 10.
{ phone: null, $exists: true }❌ NoYes❌ NoMatches explicit nulls while filtering out missing fields.

Capped Collections: High-Throughput FIFO Circular Buffers

A Capped Collection is a fixed-size, circular FIFO (First-In, First-Out) collection designed for high-throughput logging, telemetry buffering, and real-time event streaming. When a capped collection fills its allocated disk space, it automatically overwrites its oldest documents in natural insertion order without index fragmentation.

Creation Syntax

// Create a capped collection of 10 MB with a maximum of 5,000 documents
db.createCollection("system_audit_events", {
  capped: true,
  size: 10485760, // Mandatory: Maximum size in bytes (10 MB)
  max: 5000       // Optional: Maximum number of documents allowed
});
  • size (Number, Mandatory): The maximum storage quota in bytes allocated for the collection. WiredTiger pre-allocates space.
  • max (Number, Optional): The maximum document count ceiling. If the document count reaches max before the byte size is exhausted, older documents are purged.

Strict Operational Constraints (High-Yield Exam Topics)

  1. No Individual Document Deletions: You CANNOT execute deleteOne() or deleteMany() on a capped collection. Calling delete throws an error: cannot remove from a capped collection. To clear a capped collection, you must drop() the entire collection and recreate it.
  2. No Size-Expanding Updates: Document updates are permitted ONLY if the updated document does not increase in byte size. An update that causes the document to expand beyond its original on-disk allocation throws a cannot grow document in capped collection error.
  3. Natural Insertion Order: Documents are permanently ordered on disk by insertion sequence. Queries without a $sort naturally return documents in chronological insertion order.
  4. Cannot Be Sharded: Capped collections cannot be partitioned across a sharded cluster.

Tailable Cursors

Capped collections support Tailable Cursors (conceptually identical to the Unix tail -f command). Unlike standard cursors which close when the client reaches the end of the result set, a tailable cursor remains open, waiting for new documents to be inserted:

// Opening an awaiting tailable cursor in mongosh / driver
const cursor = db.system_audit_events.find()
  .tailable({ awaitData: true });

while (cursor.hasNext()) {
  printjson(cursor.next());
}

Time-Series Collections: Optimized Temporal Metric Pipelines

Introduced to natively handle high-frequency sensor telemetry, stock ticks, and IoT metrics, Time-Series Collections store temporal sequences using columnar compressed storage buckets under the hood (managed in internal system.buckets collections).

Creation Syntax

db.createCollection("weather_metrics", {
  timeseries: {
    timeField: "timestamp",       // Mandatory: Top-level date field
    metaField: "sensor_metadata",  // Optional: Identifying metadata subdocument/string
    granularity: "minutes",        // Optional: 'seconds' | 'minutes' | 'hours' (default: 'seconds')
    bucketMaxSpanSeconds: 3600    // Optional: Max time span per bucket
  },
  expireAfterSeconds: 2592000     // Optional: TTL automatic expiration (30 days)
});
  • timeField (String, Mandatory): The name of the top-level document field containing the BSON Date timestamp for the measurement.
  • metaField (String, Optional): The name of the field containing static metadata identifying the source entity (e.g., { sensor_id: "SN-882", location: "Building-4" }). MongoDB automatically builds a compound index on { [metaField]: 1, [timeField]: 1 }.
  • granularity (String, Optional): Defines the sampling frequency: "seconds" (default), "minutes", or "hours". Setting the proper granularity optimizes the internal bucketing interval and maximizes compression.
Collection TypeData Ingestion ModelPurge / Deletion StrategySharding SupportBest Use Case
StandardGeneral purposeFull CRUD (deletions, updates)✅ YesUser profiles, orders, catalogs
CappedHigh-throughput append-onlyAutomatic FIFO circular overwrite❌ NoSystem logs, audit trails, event feeds
Time-SeriesColumnar append-onlyTTL index (expireAfterSeconds)✅ YesIoT telemetry, metrics, financial ticks

Practical Collection Management in mongosh

use telemetry_db;

// 1. Create a capped audit collection with a 5MB size limit
db.createCollection("app_logs", { capped: true, size: 5242880, max: 10000 });

// 2. Verify capped status
const isCapped = db.app_logs.isCapped();
print("Collection is capped:", isCapped); // true

// 3. Insert telemetry records
db.app_logs.insertOne({ event: "LOGIN_SUCCESS", user_id: 42, timestamp: new Date() });

// 4. Attempting an illegal deletion (Throws MongoServerError: cannot remove from a capped collection)
try {
  db.app_logs.deleteOne({ user_id: 42 });
} catch (err) {
  print("Caught expected error:", err.message);
}

// 5. Query differentiating null from missing values in user settings
db.user_settings.find({ notification_channel: { $type: "null" } }); // Exact explicit nulls
db.user_settings.find({ notification_channel: { $exists: false } }); // Completely missing
Loading diagram...
Capped Collection Circular Buffer vs. Time-Series Columnar Bucketing Mechanics
Test Your Knowledge

An operational engineering team implements a capped collection to record application security audit logs. Which operation is strictly prohibited and will result in a runtime error when executed against this collection?

A
B
C
D
Test Your Knowledge

A developer runs the query db.orders.find({ discount_code: null }). Which documents in the collection will be returned by this query?

A
B
C
D
Test Your Knowledge

Under the WiredTiger storage engine, what is the maximum allowable namespace length for a MongoDB collection (<database>.<collection>), and what is a forbidden collection naming convention?

A
B
C
D
Test Your Knowledge

When creating a Time-Series collection using db.createCollection('telemetry', { timeseries: { ... } }), which configuration property inside the timeseries option object is mandatory?

A
B
C
D