Indexes
By default, every collection has an index on the _docID property.
The @index directive allows you to set up further indexes on selected properties.
@index(
name: String,
unique: Bool,
direction: ORDERING,
includes: [{ field: String, direction: ORDERING }]
)
name– Index name.
Default: concatenation of collection name, field names, direction.unique– Enforce uniqueness constraint (i.e. no two documents can have the same value for the given fields).
Default:false.direction– The index order. This affects the default sorting of results when querying documents.
Valid values:ASCorDESC.
Default:ASC.includes– List of fields the index is created on. (Not required when the directive is used in a field definition).
Index for individual fields
To create an index for a specific field in a collection, use the @index directive when defining the field.
type Book {
title: String @index
}
type Book {
title: String @index(name: "book_title")
plot: String @index(name: "book_plot")
}
type Book {
title: String
author: Person @primary @index
}
type Person {
name: String
books: [Book]
}
Unique indexes
An indexed unique field ensures that no two documents have the same value for one field. Null values are still allowed though.
type Book {
title: String @index(unique: true)
}
When applied to a relationship field, the @index(unique: true) makes it into a one-to-one relationship. In the example below, no two User can share the same Address.
type User {
name: String
age: Int
address: Address @primary @index(unique: true)
}
type Address {
user: User
city: String
street: String
}
Index for multiple fields (composite)
To create an index on the combination of multiple fields (composite index), use the @index directive at the collection level.
type User @index(unique: true, includes: [{field: "title"}, {field: "plot"}]) {
title: String
plot: String
}
JSON fields indexing
JSON fields are treated specially: their leaf nodes are indexed, so that their structure can be traversed in queries. Each JSON field generates multiple entries in the index: one for every leaf node, each with their value and path. For example, given a property of JSON format with the following value:
{
"user": {
"device": {
"os": "Linux"
}
}
}
Assuming an index is present on Collections.jsonField, you can query documents of that type filtering on the user.device.os property:
query {
Collection(filter: {
jsonField: {
user: {
device: {
model: {_eq: "Linux"}
}
}
}
})
}
Scalar types (ex. integers) are normalized to standard types (ex. int64).
Performance considerations
More indexes is not better. The right indexes is better.
Although an index can improve read performance, it will decrease write performance, because every document update/create must also update the relevant indexes.
- Create indexes based on your query patterns. If you are tempted to index every field, remember that there's no free lunch and that the overhead (in storage and write speed) is likely to outweigh the benefit.
- Use unique indexes only when necessary. Because they require extra validation, their performance impact is more significant.