file-json-db

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:

// 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