This page is indended 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!
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 are analogous to tables in SQL. The can contain properties—which can correspond to any scalar type— and links—which correspond to other object types.
The property
keyword is used to declare a property.
type Movie {
title: str;
}
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.
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.
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;
property uppercase_title := str_upper(.title);
}
See Schema > Computeds.
Object types can have links to other object types.
type Movie {
required title: str;
director: Person;
}
type Person {
required name: str;
}
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.
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 link same_title := (
with t := .title
select detached Movie filter .title = t
)
}
A common use case for computed links is backlinks.
type Movie {
required title: str;
multi actors: Person;
}
type Person {
required name: str;
multi link 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 called actors
that points to the current object. This set could
conceivably contain other objects besides Movie
; for instance, we could
define a TVShow
type that also included link 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 besides `` Movie`` objects.
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);
}
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.
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;
}
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.