# Indexing

Indexing is a way to optimize the performance of a database by minimizing the number of disk accesses required when a query is processed. It is a data structure technique which is used to quickly locate and access the data in a database.

Nitrite supports indexing on a collection. It supports indexing on a single field or multiple fields. It also supports full-text indexing.

# Index Types

Nitrite supports the following types of index out of the box:

  • Unique Index
  • Non-Unique Index
  • Full-text Index

# Unique Index

A unique index ensures that the indexed field contains unique value. It does not allow duplicate value in the indexed field. It also ensures that the indexed field is not null.

# Non-unique Index

A non-unique index does not ensure that the indexed field contains unique value. It allows duplicate value in the indexed field.

# Full-text Index

A full-text index is used to search text content in a document. It is useful when you want to search text content in a document. It is also useful when you want to search text content in a document in a language other than English.

# Custom Index

You can also create your own custom index. You need to implement NitriteIndexer interface to create your own custom index. NitriteIndexer is a NitritePlugin, so you need to register it using loadModule() method while opening a database. During index creation you need to pass the type of the custom index in IndexOptions object.

One of such custom index implementation can be found in spatial module. It provides spatial indexing on a collection. More on spatial indexing can be found here.

# Creating an Index

You can create an index on a collection using createIndex() method. There are several overloaded version of createIndex() method. You can create an index on a single field or multiple fields.

# Creating a Unique Index

You can create a unique index on a single field or multiple fields. It takes the name of the fields on which the index will be created as input parameter.

// create a unique index on a single field
await collection.createIndex(["firstName"]);

// create a unique index on multiple fields
await collection.createIndex(["firstName", "lastName"]);

# Creating a Non-unique Index

You can create a non-unique index on a single field or multiple fields by passing the index type as IndexType.nonUnique in IndexOptions object and the name of the fields on which the index will be created as input parameters.

// create a non-unique index on a single field
await collection.createIndex(["firstName"], indexOptions(IndexType.nonUnique));

// create a non-unique index on multiple fields
await collection.createIndex(["firstName", "lastName"], indexOptions(IndexType.nonUnique));

# Creating a Full-text Index

You can create a full-text index on a single field by passing the index type as IndexType.fullText in IndexOptions object and the name of the fields on which the index will be created as input parameters.

// create a full-text index on a single field
await collection.createIndex(["firstName"], indexOptions(IndexType.fullText));

# Creating Index on Array Field

Nitrite supports creating index on array field. It will create index on each element of the array. For example, if you have a document like this:

{
    "firstName": "John",
    "lastName": "Doe",
    "age": 30,
    "address": "123 Street",
    "phones": ["1234567890", "0987654321"]
}

You can create index on phones field like this:

// create unique index on array field
await collection.createIndex(["phones"]);

// create non-unique index on array field
await collection.createIndex(["phones"], indexOptions(IndexType.nonUnique));

# Creating Index on Nested Field

You can create index on nested field. For example, if you have a document like this:

{
    "firstName": "John",
    "lastName": "Doe",
    "age": 30,
    "phones": ["1234567890", "0987654321"],
    "address": {
        "street": "123 Street",
        "city": "New York",
        "state": "NY",
        "zip": "10021"
    }
}

You can create index on street field like this:

// create unique index on nested field
await collection.createIndex(["address.street"]);

# Rebuilding an Index

You can rebuild an index on a collection using rebuildIndex() method. It takes the name of the fields on which the index will be rebuilt as input parameter.

// rebuild index on a single field
await collection.rebuildIndex(["firstName"]);

// rebuild index on multiple fields
await collection.rebuildIndex(["firstName", "lastName"]);

# Dropping an Index

You can drop an index on a collection using dropIndex() method. It takes the name of the fields on which the index will be dropped as input parameter.

// drop index on a single field
await collection.dropIndex(["firstName"]);

// drop index on multiple fields
await collection.dropIndex(["firstName", "lastName"]);

# Dropping All Indexes

You can drop all indexes on a collection using dropAllIndices() method.

await collection.dropAllIndices();

# Getting All Indexes

You can get all indexes on a collection using listIndices() method. It returns a Future<Collection> of IndexDescriptor object.

Collection<IndexDescriptor> indexes = await collection.listIndices();

# IndexDescriptor

IndexDescriptor is a simple class which contains the following information about an index:

  • collectionName: The name of the collection on which the index is created.
  • indexType: The type of the index.
  • fields: A Fields object containing the name of the fields on which the index is created.

# Checking If an Index Exists

You can check if an index exists on a collection using hasIndex() method. It takes the name of the fields on which the index will be checked as input parameter.

// check if an index exists on a single field
bool exists = await collection.hasIndex(["firstName"]);

// check if an index exists on multiple fields
bool exists = await collection.hasIndex(["firstName", "lastName"]);

# Error Scenarios

The following error scenarios are possible while creating an index:

  • If another index of any type is already created on the collection on the same field(s), then it will throw IndexingException.
  • If a unique index is created on a field and the field contains duplicate value, then it will throw UniqueConstraintException.
  • If a full-text index is created on multiple fields, then it will throw IndexingException.
  • If a full-text index is created on a field which is not a String, then it will throw IndexingException.
  • If you try to drop an index which does not exist, then it will throw IndexingException.
  • If you try to rebuild an index which does not exist, then it will throw IndexingException.