Skip to main content
Version: 1.0 RC1 (Latest)

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 directive syntax
@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: ASC or DESC.
    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.

Index the title property using default values
type Book {
title: String @index
}
Index multiple properties, separately, overriding defaults for name
type Book {
title: String @index(name: "book_title")
plot: String @index(name: "book_plot")
}
Index a relationship property
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.

Index the title property and enforce value uniqueness
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.

Define a one-to-one relationship between User and 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.

(Unique) Index for (name, plot)
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"}
}
}
}
})
}
note

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.