인덱스 속성: 고유, 희소, 부분, TTL
학습자는 고유, 희소, 부분, TTL 속성을 가진 특수 인덱스를 만들어 제약 조건을 적용하고 정리 작업을 자동화합니다.
인덱스 속성: 고유, 희소, 부분, TTL은(는) CoddyKit의 무료 MongoDB Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 MongoDB Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Index Properties Overview
Beyond the basic B-tree structure, MongoDB indexes support several property modifiers that change how they behave: unique enforces distinctness, sparse skips null entries, partial limits the index to a subset of documents, and TTL automatically expires documents. Each property is set in the options object of createIndex() and serves a specific purpose in production schemas.
Unique Indexes
A unique index guarantees that no two documents in the collection can have the same value for the indexed field. Any insert or update that would produce a duplicate triggers a DuplicateKey error. Unique indexes are commonly used on fields like email, username, or any natural key. The _id index is always unique.
// Unique index on email
db.users.createIndex(
{ email: 1 },
{ unique: true }
);
// First insert succeeds
db.users.insertOne({ email: 'alice@example.com', name: 'Alice' });
// Second insert with same email throws E11000 DuplicateKey
db.users.insertOne({ email: 'alice@example.com', name: 'Bob' });Unique Compound Indexes
Unique constraints can span multiple fields in a compound index. The uniqueness check applies to the combination of the indexed fields, not each field individually. This is perfect for modelling relationships like 'a user can only follow another user once' without a separate lookup query.
// A user can only 'follow' each other user once
db.follows.createIndex(
{ followerId: 1, followingId: 1 },
{ unique: true }
);
// This succeeds
db.follows.insertOne({ followerId: 'u1', followingId: 'u2' });
// This fails - same pair already exists
db.follows.insertOne({ followerId: 'u1', followingId: 'u2' });Sparse Indexes
By default, a MongoDB index includes entries for every document, even those where the indexed field is missing (stored as null). A sparse index only includes documents that have the indexed field. This is useful for optional fields that appear in only a small subset of documents—without sparse, every null/missing document would bloat the index unnecessarily.
// Only documents WITH a phoneNumber are indexed
db.users.createIndex(
{ phoneNumber: 1 },
{ sparse: true }
);
// This document is NOT in the index (phoneNumber absent)
db.users.insertOne({ name: 'Alice', email: 'a@b.com' });
// This document IS in the index
db.users.insertOne({ name: 'Bob', phoneNumber: '+1555000' });Sparse Unique: Optional Unique Fields
Combining sparse: true with unique: true lets you create a unique constraint on an optional field. Without sparse, a unique index would only allow one document to omit the field (since all missing values would be stored as null and null must be unique). Sparse + unique means: if the field exists, it must be distinct; if it's missing, the document is simply excluded from the index.
// Optional unique twitterHandle
db.users.createIndex(
{ twitterHandle: 1 },
{ unique: true, sparse: true }
);
// Multiple users without twitterHandle are all allowed
db.users.insertMany([
{ name: 'Alice' },
{ name: 'Bob' },
{ name: 'Carol', twitterHandle: '@carol' }
]);Partial Indexes
A partial index indexes only the documents that match a partialFilterExpression. This is more flexible than sparse (which only checks for field existence) because you can specify any filter condition. Partial indexes are smaller and faster to maintain than full indexes when a query always includes a predictable filter on the collection.
// Only index orders that are 'active' - skips completed/cancelled
db.orders.createIndex(
{ userId: 1, createdAt: -1 },
{
partialFilterExpression: { status: 'active' },
name: 'idx_orders_active'
}
);
// This query hits the partial index because it includes status:active
db.orders.find({ userId: 'u1', status: 'active' })
.sort({ createdAt: -1 });Partial Index Query Requirements
MongoDB can use a partial index only when the query guarantees that it requests a subset of the documents covered by the index. In practice, this means your query filter must include the same condition as the partialFilterExpression. Queries that don't include this condition will fall back to a collection scan or another index because the partial index might be missing matching documents.
// Partial index only covers status: 'active'
// USES the partial index (filter includes status: 'active')
db.orders.find({ userId: 'u1', status: 'active' });
// DOES NOT USE the partial index (query might return completed orders)
db.orders.find({ userId: 'u1' });
// MongoDB must use full scan or a different index hereTTL Indexes: Automatic Expiry
A TTL (Time-To-Live) index is a special single-field index on a date field that tells MongoDB to automatically delete documents after a specified number of seconds. A background thread runs every 60 seconds and removes expired documents. TTL indexes are perfect for session data, cache entries, audit logs, and any data with a natural shelf life.
// Automatically delete sessions 24 hours after 'createdAt'
db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 86400 } // 86400 = 24 * 60 * 60
);
// Insert a session - it will auto-delete after 24h
db.sessions.insertOne({
userId: 'u1',
token: 'abc123',
createdAt: new Date()
});TTL on a Specific Expiry Field
Instead of a fixed duration from creation, you can set expireAfterSeconds: 0 and store the exact expiry timestamp in the indexed date field. MongoDB will delete each document at the moment the stored date passes. This gives you per-document control over expiry, useful for subscription end dates, JWT token expiry, or scheduled job cleanup.
// Delete each document at its own 'expiresAt' time
db.tokens.createIndex(
{ expiresAt: 1 },
{ expireAfterSeconds: 0 }
);
// This token expires in 1 hour
const oneHourFromNow = new Date(Date.now() + 3600 * 1000);
db.tokens.insertOne({
userId: 'u1',
value: 'tok_xyz',
expiresAt: oneHourFromNow
});TTL Limitations to Know
TTL indexes have a few important restrictions: the indexed field must be a BSON date (not a string); TTL indexes cannot be compound; the background cleanup thread runs approximately every 60 seconds so there is a small delay between expiry time and actual deletion; and TTL indexes do not apply to capped collections. The 60-second delay is usually acceptable but matters for high-precision use cases.
// TTL only works on ISODate fields, not strings
// WRONG - will NOT expire:
db.logs.insertOne({ ts: '2024-01-01T00:00:00Z' });
// CORRECT - will expire:
db.logs.insertOne({ ts: new Date('2024-01-01T00:00:00Z') });
// Also, TTL cannot be compound:
// This is INVALID:
db.logs.createIndex({ ts: 1, userId: 1 }, { expireAfterSeconds: 3600 });Choosing the Right Index Property
Use unique to enforce natural keys and prevent duplicates. Use sparse when a field is optional and present in only a minority of documents. Use partial when queries always include a known filter condition and you want a leaner index. Use TTL to automate data expiry without application-level cron jobs. These properties can be combined: unique + sparse is common for optional unique identifiers.
// Summary of all four property types
// Unique
db.users.createIndex({ email: 1 }, { unique: true });
// Sparse
db.users.createIndex({ phone: 1 }, { sparse: true });
// Partial
db.orders.createIndex({ userId: 1 }, { partialFilterExpression: { status: 'pending' } });
// TTL
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });Quick Check
Test your understanding of MongoDB index properties from this lesson.
Lesson Recap
In this lesson you learned: unique indexes enforce distinctness on one or multiple fields, sparse indexes skip documents that lack the indexed field, partial indexes index only documents matching a filter expression, and TTL indexes automatically delete expired documents. Next up we learn to read explain() output to diagnose slow queries.
자주 묻는 질문
“인덱스 속성: 고유, 희소, 부분, TTL” 강의는 무료인가요?
네 — “인덱스 속성: 고유, 희소, 부분, TTL” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 MongoDB Academy 강의 전체를 잠금 해제할 수 있습니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“인덱스 속성: 고유, 희소, 부분, TTL”에서 뭘 배우나요?
학습자는 고유, 희소, 부분, TTL 속성을 가진 특수 인덱스를 만들어 제약 조건을 적용하고 정리 작업을 자동화합니다. 브라우저에서 직접 실행하는 실습 코드로 MongoDB Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
MongoDB Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 MongoDB Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“인덱스 속성: 고유, 희소, 부분, TTL” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 MongoDB Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 MongoDB Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- MongoDB B-Tree 인덱스의 작동 방식
- 단일 필드 및 복합 인덱스 만들기
- 인덱스 속성: 고유, 희소, 부분, TTL
- explain() 출력으로 쿼리 진단하기