# 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 repository. It supports indexing on a single field or multiple fields. It also supports full-text indexing.

Indexes for an entity can be defined using various annotations like @Id, @Index etc. More information about annotations can be found here. It can also be managed using various methods of ObjectRepository interface.

# 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 an entity. It is useful when you want to search text content in an entity. It is also useful when you want to search text content in an entity in a language other than English.

# Custom Index

You can also create your own custom index. More information about custom index can be found here.

# Creating an Index

You can define indexes for an entity using annotations. You can also create indexes using ObjectRepository interface.

# 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.

# Using Annotations

You can create a unique index on a single field or multiple fields using annotations. You can use @Id annotation to create a unique index on a single field. You can use @Index annotation to create a unique index on multiple fields.

@Entity(indices: [
  Index(fields: ['tags'], type: IndexType.nonUnique),
  Index(fields: ['description'], type: IndexType.fullText),
  Index(fields: ['price', 'publisher']),
])
class Book {
  @Id()
  int id;
  String title;
  String description;
  String publisher;
  List<String> tags;
  double price;

  Book(this.title, this.description, this.publisher, this.tags, this.price);
}

# Using ObjectRepository

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

await bookRepository.createIndex(['tags']);
await bookRepository.createIndex(['price', 'publisher']);

# 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.

# Using Annotations

You can create a non-unique index on a single field or multiple fields using annotations. You can use @Index annotation to create a non-unique index on multiple fields.

@Entity(indices: [
  Index(fields: ['tags'], type: IndexType.nonUnique),
  Index(fields: ['price', 'publisher'], type: IndexType.nonUnique),
])
class Book {
  @Id()
  int id;
  String title;
  String description;
  String publisher;
  List<String> tags;
  double price;

  Book(this.title, this.description, this.publisher, this.tags, this.price);
}

# Using ObjectRepository

You can create a non-unique index on a single field or multiple fields using createIndex() method. It takes the name of the fields on which the index will be created as input parameter and the index type as IndexType.nonUnique.

await bookRepository.createIndex(['tags'], indexOptions(IndexType.nonUnique));
await bookRepository.createIndex(['price', 'publisher'], indexOptions(IndexType.nonUnique));

# Creating a Full-text Index

You can create a full-text index on a single field or multiple fields by passing the index type as IndexType.fullText.

# Using Annotations

You can create a full-text index on a single field using annotations. You can use @Index annotation to create a full-text index on a single field.

@Entity(indices: [
  Index(fields: ['description'], type: IndexType.fullText),
])
class Book {
  @Id()
  int id;
  String title;
  String description;
  String publisher;
  List<String> tags;
  double price;

  Book(this.title, this.description, this.publisher, this.tags, this.price);
}

# Using ObjectRepository

You can create a full-text index on a single field using createIndex() method. It takes the name of the fields on which the index will be created as input parameter and the index type as IndexType.fullText.

await bookRepository.createIndex(['description'], indexOptions(IndexType.fullText));

# Creating Index on Iterable Field

Nitrite supports creating index on iterable field. It will create index on each element of the iterable. For example, if you have an entity like this:

@Entity(indices: [
  Index(fields: ['tags'], type: IndexType.nonUnique),
])
class Book {
  @Id()
  int id;
  String title;
  String description;
  String publisher;
  List<String> tags;
  double price;

  Book(this.title, this.description, this.publisher, this.tags, this.price);
}

Then it will create index on each element of the tags list. You can also create index on tags field like this:

await bookRepository.createIndex(['tags'], indexOptions(IndexType.nonUnique));

# Creating Index on Embedded Field

Nitrite supports creating index on embedded field. For example, if you have entities like this:

@Entity(indices: [
  Index(fields: ['address.city'], type: IndexType.nonUnique),
])
class Person {
  @Id()
  int id;
  String name;
  Address address;

  Person(this.name, this.address);
}

class Address {
  String city;
  String state;
  String country;

  Address(this.city, this.state, this.country);
}

Then it will create index on city field of Address entity. You can also create index on city field of Address entity like this:

await personRepository.createIndex(['address.city'], indexOptions(IndexType.nonUnique));

# Rebuilding an Index

You can rebuild an index 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 bookRepository.rebuildIndex(['tags']);

// rebuild index on multiple fields
await bookRepository.rebuildIndex(['price', 'publisher']);

# Dropping an Index

You can drop an index 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 bookRepository.dropIndex(['tags']);

// drop index on multiple fields
await bookRepository.dropIndex(['price', 'publisher']);

# Dropping All Indexes

You can drop all indexes using dropAllIndices() method.

await bookRepository.dropAllIndices();

# Getting All Indexes

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

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

# IndexDescriptor

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

  • 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 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 bookRepository.hasIndex(['tags']);

// check if an index exists on multiple fields
bool exists = await bookRepository.hasIndex(['price', 'publisher']);

# Error Scenarios

The following error scenarios are possible while creating an index:

  • If another index of any type is already created on the repository 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.