Study guide
5.4 Specialized Index Types: TTL, Partial, Unique & Text
MongoDB Associate Developer Exam
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Document Model & MongoDB Architecture
1.1 Document Model Fundamentals & BSON Data Types 1.2 Databases, Collections & Schema Flexibility 1.3 Distributed Architecture Fundamentals: Replica Sets & Sharded Clusters
2 Chapter 2: CRUD Operations: Create & Read
2.1 Document Insertion Operations 2.2 Query Selectors & Filter Operators 2.3 Array Queries & Element Evaluation 2.4 Projections, Cursor Methods & Collation
3 Chapter 3: CRUD Operations: Update & Delete
3.1 Field Update Operators 3.2 Array Update Operators & Positional Modifiers 3.3 Document Replacement & Deletion Operations 3.4 Atomic Find-and-Modify Operations
4 Chapter 4: Aggregation Framework Mastery
4.1 Pipeline Fundamentals & Core Stages ($match, $project, $addFields) 4.2 Grouping, Reshaping & Array Manipulation ($group, $unwind, $replaceWith) 4.3 Multi-Document Joins & Faceted Pipelines ($lookup, $facet, $bucket) 4.4 Materialization & Window Operations ($out, $merge, $setWindowFields) 4.5 Atlas Search: Search Index Definitions & $search Queries
5 Chapter 5: Indexing Strategies & Performance Optimization
5.1 Index Types & Storage Mechanics 5.2 Compound Indexes & the Equality-Sort-Range (ESR) Rule 5.3 Multikey Indexes & Array Indexing Constraints 5.4 Specialized Index Types: TTL, Partial, Unique & Text 5.5 Query Optimization & Explain Plan Analysis
6 Chapter 6: Data Modeling & Schema Design Patterns
6.1 Embedding vs. Referencing Tradeoffs 6.2 Core Schema Design Patterns 6.3 Schema Validation with JSON Schema
7 Chapter 7: Application Development & Driver Integration
7.1 Connection Strings & Connection Pool Management 7.2 Driver CRUD Paradigms & Object Mapping 7.3 Cursor Batching, Streaming & Memory Handling 7.4 Write Concerns, Read Concerns & Retryable Operations
8 Chapter 8: Developer Tooling & Administration Essentials
8.1 mongosh Scripting & Administrative Commands 8.2 Data Ingestion & Export Utilities 8.3 Backup, Restore & Performance Telemetry 8.4 Atlas Sample Dataset & Data Explorer
5.4 Specialized Index Types: TTL, Partial, Unique & Text
Key Takeaways Explain This Topic AI
TTL (Time-To-Live) indexes automatically delete documents after a specified duration using a background thread running every 60 seconds; they must be single-field Date indexes and cannot be compound or built on '_id'.
Partial indexes index only documents matching a specified 'partialFilterExpression', drastically reducing index memory footprint and write overhead.
Unique indexes reject duplicate key values; combining unique constraints with partialFilterExpression allows enforcing uniqueness on populated fields while ignoring missing or null fields.
A collection can have at most ONE Text index, which supports full-text search, tokenization, language stemming, and relevance sorting via '{ score: { $meta: "textScore" } }'.
2dsphere geospatial indexes index GeoJSON geometry on an Earth-like sphere using [longitude, latitude] coordinate pairs, enabling proximity queries with $near and containment queries with $geoWithin.
Last updated: September 2026
Specialized Index Types: TTL, Partial, Unique & Text
Exam Focus: The MongoDB Certified Associate Developer Exam tests the exact configuration parameters, mechanics, and limitations of specialized index types: TTL index date requirements and 60-second background thread purge cycles, Partial Index partialFilterExpression query matching rules, Unique Index null-handling and Partial Unique patterns, Text Index single-index limits and $text / textScore syntax, and 2dsphere GeoJSON coordinate ordering ( [longitude, latitude] ).
1. Time-To-Live (TTL) Indexes
A TTL (Time-To-Live) Index is a specialized single-field index that automatically purges documents from a collection after a specified amount of time. TTL indexes are ideal for transient operational data such as user authentication sessions, temporary verification tokens, machine telemetry caches, and ephemeral event logs.
- Syntax & Configuration // Expire documents 3600 seconds (1 hour) after the 'created_at' timestamp
- db.user_sessions.createIndex(
- { created_at: 1 },
- { expireAfterSeconds: 3600 }
- );
- Fixed-Interval Expiration vs. Dynamic Custom Expiration
Fixed-Interval Expiration: As shown above, every document expires when current_time >= created_at + expireAfterSeconds .
Dynamic Custom Expiration (Per-Document TTL): Set expireAfterSeconds: 0 and store the explicit future expiration date in each document's Date field: // Create dynamic TTL index
db.coupons.createIndex({ expires_at: 1 }, { expireAfterSeconds: 0 });
- // Document with custom future expiration date
- db.coupons.insertOne({
- code: "SPRING2026",
- expires_at: ISODate("2026-09-15T00:00:00Z") // Purged after this exact instant
- });
- Critical TTL Rules & Limitations (High-Yield Exam Points)
BSON Date Type Requirement: The indexed field must contain a BSON Date ( ISODate ) or an array of BSON Dates. If the field contains a string, timestamp, integer, or null, the document will never be expired.
Single-Field Only: TTL indexes cannot be compound indexes .
Forbidden on _id : You cannot build a TTL index on the primary key _id .
60-Second Background Thread: Document deletion is managed by an internal background thread that executes once every 60 seconds . Therefore, document expiration is not instantaneous; a document may remain visible for up to 60 seconds after its expiration threshold.
Capped Collections Incompatibility: TTL indexes cannot be created on capped collections because capped collections prohibit individual document deletions.
Modifying TTL Thresholds: You can modify expireAfterSeconds on an existing index using the collMod command without dropping and rebuilding the index: db.runCommand({
- collMod: "user_sessions",
- index: {
- keyPattern: { created_at: 1 },
- expireAfterSeconds: 7200 // Extended to 2 hours
- }
- });
- 2. Partial Indexes
A Partial Index indexes only documents in a collection that satisfy a specified filter expression ( partialFilterExpression ). By omitting documents that are never queried, partial indexes reduce index size in RAM, minimize disk usage, and cut write maintenance overhead.
- Syntax // Index 'email' ONLY for documents where status is 'ACTIVE'
- db.users.createIndex(
- { email: 1 },
- { partialFilterExpression: { status: "ACTIVE" } }
- );
- Query Utilization Rules for Partial Indexes
For MongoDB to use a partial index during query execution, the query filter must be a guaranteed subset of the partialFilterExpression : // Uses the partial index (filter explicitly includes status: "ACTIVE"):
db.users.find({ email: "alex@example.com", status: "ACTIVE" });
// CANNOT use the partial index (filter does not guarantee status is "ACTIVE"):
- db.users.find({ email: "alex@example.com" }); // Triggers COLLSCAN
- Allowed Operators in partialFilterExpression
The partialFilterExpression supports: $eq , $exists: true , $gt , $gte , $lt , $lte , $type , and $and at the top level. Operators such as $expr , $where , $text , and $regex are not permitted.
3. Unique Indexes & The Partial Unique Pattern
A Unique Index guarantees that the indexed field does not store duplicate values across the collection, rejecting any write operation that violates uniqueness with an E11000 duplicate key error .
- Syntax db.accounts.createIndex({ username: 1 }, { unique: true });
- The Missing/Null Field Problem in Unique Indexes
In MongoDB, if a document does not contain an indexed field, MongoDB stores null as the index entry. Consequently, in a standard unique index, you can insert at most ONE document that lacks the indexed field . A second insert with a missing or null field throws an E11000 duplicate key error on { field: null } !
The Solution: Partial Unique Indexes (Modern Best Practice)
To enforce uniqueness on a field when present while allowing multiple documents to omit the field, combine unique: true with a partialFilterExpression : // Allow multiple users without phone numbers, but enforce uniqueness for all existing phones
- db.users.createIndex(
- { phone_number: 1 },
- {
- unique: true,
- partialFilterExpression: { phone_number: { $type: "string" } }
- }
- );
Tip
Partial Unique vs Sparse Indexes: While legacy MongoDB supported sparse: true indexes, Partial Unique indexes are strictly preferred because sparse indexes only check field existence ( $exists ), whereas partialFilterExpression allows fine-grained type and value constraints.
4. Text Indexes & Full-Text Search
MongoDB provides Text Indexes to support text search queries on string content, featuring natural language tokenization, stemming (e.g., matching "running" to "run"), and case-insensitive matching.
- Key Rules & Syntax // Create a text index on multiple string fields
- db.articles.createIndex(
- { title: "text", body: "text" },
- { weights: { title: 10, body: 1 }, name: "idx_article_text_search" }
- );
Single Text Index Limit: A collection can have at most ONE text index . However, a single text index can compound multiple fields (compound text index) or index all string fields using wildcard syntax ( { "$**": "text" } ).
Executing Queries with $text and $search : // Search for articles containing 'mongodb' AND 'performance', but NOT 'legacy'
- db.articles.find({
- $text: { $search: "mongodb performance -legacy" }
- });
Relevance Sorting via textScore : MongoDB computes a numerical relevance score for each matching document. You can project and sort by this score using $meta: "textScore" : db.articles.find(
- { $text: { $search: "wiredtiger optimization" } },
- { score: { $meta: "textScore" } }
- ).sort({
- score: { $meta: "textScore" }
- });
- 5. Geospatial 2dsphere Indexes
A 2dsphere Index supports queries that calculate geometries on an Earth-like sphere using WGS84 coordinates.
Coordinate Order: [ Longitude, Latitude ]
Warning
Critical Exam Rule: GeoJSON coordinate arrays in MongoDB strictly follow the order: [ Longitude, Latitude ] (X before Y). Reversing the coordinates ( [ Lat, Long ] ) will store invalid coordinates or cause queries to fail. // Document containing GeoJSON Point
- db.places.insertOne({
- name: "Central Park",
- location: {
- type: "Point",
- coordinates: [ -73.9654, 40.7829 ] // [ Longitude, Latitude ]
- }
- });
- // Create 2dsphere index
- db.places.createIndex({ location: "2dsphere" });
- // Proximity search: Find places within 5,000 meters
- db.places.find({
- location: {
- $near: {
- $geometry: { type: "Point", coordinates: [ -73.9654, 40.7829 ] },
- $maxDistance: 5000
- }
- }
- });
- Specialized Index Comparison Matrix
- Index Type Primary Use Case Key Configuration Option Critical Restrictions
- TTL Auto-purging transient data expireAfterSeconds: <N> Single Date field only; 60s purge loop; no capped/ _id
Partial Indexing selective subsets partialFilterExpression: <query> Queries must guarantee filter subset to utilize index
- Unique Enforcing uniqueness unique: true Multiple nulls conflict without partial filter
- Text Full-text tokenized search { field: "text" } Maximum 1 text index per collection
- 2dsphere Geospatial spherical search { field: "2dsphere" } Strict [ Longitude, Latitude ] coordinate ordering