Indexes
Indexes make equality lookups on a field much faster. Without an index the library must scan every document in every part. With an index it can jump directly to the relevant part(s).
Defining indexes
Indexes are declared when you create (or open) a collection:
const users = db.collection({
name: 'users',
autoId: true,
indexes: ['email', 'username', 'profile.city'] // nested fields work too
});
The list is stored in the collection options and is used both when inserting/updating documents and when rebuilding the index later.
How indexes are stored
Secondary indexes live inside index.json under the key indexes:
{
"indexes": {
"email": {
"alice@example.com": [{ "id": 1, "part": "0001" }],
"bob@example.com": [{ "id": 2, "part": "0001" }]
},
"username": {
"alice": [{ "id": 1, "part": "0001" }],
"bob": [{ "id": 2, "part": "0001" }]
}
}
}
Each value maps to an array of { id, part } entries so that
non-unique values are supported.
When the index is used
The query engine uses a secondary index only when:
- The query contains a simple equality condition on an indexed field, and
- That is the only condition in the query (single-field equality)
// Uses the email index → very fast
users.findOne({ email: 'alice@example.com' });
// Full scan (multiple fields or operators)
users.find({ email: 'alice@example.com', active: true }).toArray();
users.find({ age: { $gte: 18 } }).toArray();
Primary index (idIndex)
In addition to secondary indexes there is always a primary idIndex
that maps every document ID to the part that contains it.
This makes findOne({ _id: … }) fast even without an explicit secondary index.
Rebuilding indexes
If you change the list of indexed fields, or if the index becomes inconsistent (for example after manually editing part files), you can rebuild:
users.rebuildIndexes();
// Scans every part, rebuilds idIndex + secondary indexes, writes index.json
The collection also emits an index-rebuilt event when this finishes.
Best practices
- Index fields that you frequently look up by exact value (email, username, sku, status, …).
- Do not index high-cardinality fields that you only use in range queries – the index will not help.
- Keep the number of indexed fields reasonable; each index adds memory and write cost.
- Nested fields are supported:
indexes: ['address.city'].