Skip to main content

Constraints and indexes

This article describes how you can use the @container directive in GraphQL to add constraints and enhance the searchability of the data in a data type.

Indexes and constraints apply to a container, and all the involved properties must belong to the same container.

Constraints

When you build a data model, you can use ! to add a requiredness constraint. To specify more complex requirements for how data should conform to the data model, you can add multiple constraints on each data type.

Uniqueness

For uniqueness constraints, you must give it a unique (with the space) identifier, and a list of the combination of fields that needs to be unique.

The uniqueness is enforced by an underlying index. The index can boost the performance of queries that need to filter or sort on the involved properties. Therefore, the order of the properties matter.

Currently, we don't support relation fields (direct or many-to-many) for uniqueness constraints.

The example below has a my-unique-constraint constraint that checks name and description for uniqueness in combination.

type Facility
@container(
constraints: [
{
constraintType: UNIQUENESS
identifier: "my-unique-constraint"
fields: ["name", "description"]
}
]
) {
name: String
description: String

lang: Int
lat: Int
}

Views and containers

You can only specify constraints and indexes on new (non-imported) fields of a data type when using @container. See also the Limitations section.

Indexes

You can add custom indexes to containers to speed up queries by enabling fast lookups, filtering, and sorting. Indexes come at a cost, and aren't added to properties by default. For example, indexes increase storage usage, and make write operations slower, and don't guarantee that queries execute faster.

By default, you can efficiently filter all instances with the space and externalId fields.

To improve query execution, you may want to specify an explicit ordering of fields to index. In these cases, you can use the indexes of the @container directive.

Like constraints, all indexes must have an identifier that's unique within a space. Additionally, it needs a specified type (currently, we only support BTREE) and the set of properties. All the properties mentioned must be in the same container.

The field ordering defines what combinations of filters you can use, and what kinds of sorts the index supports.

If you have an index on (type, priority), queries that filter on type = ... or type = ... AND priority >= ... can use the index. Queries that sort on type or (type, priority) can use the index as a pre-sorted way of accessing the data.

However, a query that sorts or filters just on priority won't be able to use an index on (type, priority).

The example below adds a my-index index on the properties type, priority, in that order.

type WorkItem
@container(
indexes: [
{
identifier: "my-index"
indexType: BTREE
fields: ["type", "priority"]
}
]
) {
type: String
priority: Int

...
}

Combining constraints and indexes

You can combine indexes and constraints on a @container, as in this example:

type Facility
@container(
constraints: [
{
constraintType: UNIQUENESS
identifier: "my-unique-constraint"
fields: ["name", "description"]
}
{
constraintType: UNIQUENESS
identifier: "my-unique-constraint-2"
fields: ["lat", "lng"]
}
]
indexes: [
{
identifier: "my-index"
indexType: BTREE
fields: ["name", "tag", "description"]
}
]
) {
name: String
description: String

lng: Int
lat: Int
tag: String
}

Views and containers

You can only specify constraints and indexes on new (non-imported) fields of a data type when using @container.

Limitations

Since containers physically stores the data, you can only specify constraints and indexes on fields within the data type that are stored within the same container.

If the data type extends from another view (via @view or inheritance), you can't use the fields that belong in containers from the imported views to build constraints or indexes.

You can only specify constraints and indexes on new (non-imported) fields of a data type when using @container.