Schema
This page is intended as a rapid-fire overview of EdgeDB’s schema definition language (SDL) so you can hit the ground running with EdgeDB. Refer to the linked pages for more in-depth documentation!
Scalar types
EdgeDB implements a rigorous type system containing the following primitive types.
Strings |
|
Booleans |
|
Numbers |
|
UUID |
|
JSON |
|
Dates and times |
|
Durations |
|
Binary data |
|
Auto-incrementing counters |
|
Enums |
|
These primitives can be combined into arrays, tuples, and ranges.
Arrays |
|
Tuples (unnamed) |
|
Tuples (named) |
|
Ranges |
|
Collectively, primitive and collection types comprise EdgeDB’s scalar type system.
Object types
Object types are analogous to tables in SQL. They can contain properties, which can correspond to any scalar types, and links, which can correspond to any object types.
Properties
Declare a property by naming it and setting its type.
type Movie {
title: str;
}
The property
keyword can be omitted for non-computed properties since
EdgeDB v3.
Required vs optional
Properties are optional by default. Use the required
keyword to make them
required.
type Movie {
required title: str; # required
release_year: int64; # optional
}
See Schema > Properties.
Constraints
Add a pair of curly braces after the property to define additional information, including constraints.
type Movie {
required title: str {
constraint exclusive;
constraint min_len_value(8);
constraint regexp(r'^[A-Za-z0-9 ]+$');
}
}
See Schema > Constraints.
Computed properties
Object types can contain computed properties that correspond to EdgeQL expressions. This expression is dynamically computed whenever the property is queried.
type Movie {
required title: str;
uppercase_title := str_upper(.title);
}
See Schema > Computeds.
Links
Object types can have links to other object types.
type Movie {
required title: str;
director: Person;
}
type Person {
required name: str;
}
The link
keyword can be omitted for non-computed links since EdgeDB v3.
Use the required
and multi
keywords to specify the cardinality of the
relation.
type Movie {
required title: str;
cinematographer: Person; # zero or one
required director: Person; # exactly one
multi writers: Person; # zero or more
required multi actors: Person; # one or more
}
type Person {
required name: str;
}
To define a one-to-one relation, use an exclusive
constraint.
type Movie {
required title: str;
required stats: MovieStats {
constraint exclusive;
};
}
type MovieStats {
required budget: int64;
required box_office: int64;
}
See Schema > Links.
Computed links
Objects can contain “computed links”: stored expressions that return a set of objects. Computed links are dynamically computed when they are referenced in queries. The example below defines a backlink.
type Movie {
required title: str;
multi actors: Person;
# returns all movies with same title
multi same_title := (
with t := .title
select detached Movie filter .title = t
)
}
Backlinks
A common use case for computed links is backlinks.
type Movie {
required title: str;
multi actors: Person;
}
type Person {
required name: str;
multi acted_in := .<actors[is Movie];
}
The computed link acted_in
returns all Movie
objects with a link
called actors
that points to the current Person
. The easiest way to
understand backlink syntax is to split it into two parts:
.<actors
-
This uses a special syntax
.<
to return all objects in the database with a link calledactors
that points to the current object. This set could conceivably contain other objects besidesMovie
; for instance, we could define aTVShow
type that also includedlink actors -> Person
. [is Movie]
-
This is a type filter that filters out all objects that aren’t
Movie
objects. A backlink still works without this filter, but could contain any other number of objects besidesMovie
objects.
Constraints
Constraints can also be defined at the object level.
type BlogPost {
title: str;
author: User;
constraint exclusive on ((.title, .author));
}
Constraints can contain exceptions; these are called partial constraints.
type BlogPost {
title: str;
published: bool;
constraint exclusive on (.title) except (not .published);
}
Indexes
Use index on
to define indexes on an object type.
type Movie {
required title: str;
required release_year: int64;
index on (.title); # simple index
index on ((.title, .release_year)); # composite index
index on (str_trim(str_lower(.title))); # computed index
}
The id
property, all links, and all properties with exclusive
constraints are automatically indexed.
See Schema > Indexes.
Schema mixins
Object types can be declared as abstract
. Non-abstract types can extend
abstract types.
abstract type Content {
required title: str;
}
type Movie extending Content {
required release_year: int64;
}
type TVShow extending Content {
required num_seasons: int64;
}
Multiple inheritance is supported.
abstract type HasTitle {
required title: str;
}
abstract type HasReleaseYear {
required release_year: int64;
}
type Movie extending HasTitle, HasReleaseYear {
sequel_to: Movie;
}
Polymorphism
Links can correspond to abstract types. These are known as polymorphic links.
abstract type Content {
required title: str;
}
type Movie extending Content {
required release_year: int64;
}
type TVShow extending Content {
required num_seasons: int64;
}
type Franchise {
required name: str;
multi entries: Content;
}
See Schema > Links > Polymorphism and EdgeQL > Select > Polymorphic queries.