A compound index is a single B-Tree built on two or more fields. The index stores entries sorted by the first field, then by the second field within each first-field group, and so on. Because the sort order is determined by field sequence, the order of fields in a compound index definition directly determines what queries it can serve.
// Create a compound index — field order matters db.orders.createIndex( { status: 1, customerId: 1, createdAt: -1 }, { name: "idx_status_customer_created" } ) // Up to 32 fields in a single compound index // Direction (1/-1) matters for sort operations; irrelevant for single-field equality
How the B-Tree is Structured
For an index on { status: 1, customerId: 1 }, the B-Tree sorts all documents first by status, then by customerId within each status group. This means the index can efficiently locate a specific { status, customerId } pair, or all documents for a particular status — but it cannot efficiently find all documents for a particular customerId without knowing the status first.
// Conceptual layout of { status: 1, customerId: 1 } index: // "active" → C001 → doc ptr // "active" → C002 → doc ptr // "active" → C003 → doc ptr // "closed" → C001 → doc ptr // "closed" → C004 → doc ptr // "pending" → C002 → doc ptr // // Can scan: { status: "active" } — contiguous block // Cannot scan: { customerId: "C001" } — scattered throughout
{ a, b, c } partially replaces the need for standalone indexes on { a } and { a, b } — it serves all three. However, it does NOT replace { b }, { c }, or { b, c }. Always verify with explain() that the index is actually used for each query pattern.