Links

Links define a specific relationship between two object types.

See the Modeling Relations guide for a breakdown of how to model one-to-one, one-to-many, and many-to-many relationships in EdgeDB.

  1. type Person {
  2. link best_friend -> Person;
  3. }

Links are directional; they have a source (the object type on which they are declared) and a target (the type they point to).

All links have a cardinality: either single or multi. The default is single (a “to-one” link). Use the multi keyword to declare a “to-many” link.

  1. type Person {
  2. multi link friends -> Person;
  3. }

All links are either optional or required; the default is optional. Use the required keyword to declare a required link. A required link must point to at least one target instance. In this scenario, every Person must have a best_friend:

  1. type Person {
  2. required link best_friend -> Person;
  3. }

Links with cardinality multi can also be required; required multi links must point to at least one target object.

  1. type Person {
  2. property name -> str;
  3. }
  4. type GroupChat {
  5. required multi link members -> Person;
  6. }

In this scenario, each GroupChat must contain at least one person. Attempting to create a GroupChat with no members would fail.

Exclusive constraints

You can add an exclusive constraint to a link to guarantee that no other instances can link to the same target(s).

  1. type Person {
  2. property name -> str;
  3. }
  4. type GroupChat {
  5. required multi link members -> Person {
  6. constraint exclusive;
  7. }
  8. }

In the GroupChat example, the GroupChat.members link is now exclusive. No two GroupChats can link to the same Person; put differently, no Person can be a member of multiple GroupChats.

The combination of link cardinality and exclusive constraints are sufficient to model all kinds of relations: one-to-one, one-to-many, and many-to-many. For details, read the Modeling Relations guide.

Default values

Like properties, links can declare a default value in the form of an EdgeQL expression, which will be executed upon insertion. In the example below, new people are automatically assigned three random friends.

  1. type Person {
  2. required property name -> str;
  3. multi link friends -> Person {
  4. default := (select Person order by random() limit 3);
  5. }
  6. }

In EdgeDB, links can store properties. Like object types, links can contain properties. Link properties can be used to store metadata about links, such as when it was created or the nature/strength of the relationship.

  1. type Person {
  2. property name -> str;
  3. multi link family_members -> Person {
  4. property relationship -> str;
  5. }
  6. }

Above, we model a family tree with a single Person type. The Person. family_members link is a many-to-many relation; each family_members link can contain a string relationship describing the relationship of the two individuals.

Due to how they’re persisted under the hood, link properties must always be single and optional.

For a full guide on modeling, inserting, updating, and querying link properties, see the Using Link Properties guide.

Deletion policies

Links can declare their own deletion policy. There are two kinds of events that might trigger these policies: target deletion and source deletion.

Target deletion

Target deletion policies determine what action should be taken when the target of a given link is deleted. They are declared with the on target delete clause.

  1. type MessageThread {
  2. property title -> str;
  3. }
  4. type Message {
  5. property content -> str;
  6. link chat -> MessageThread {
  7. on target delete delete source;
  8. }
  9. }

The Message.chat link in the example uses the delete source policy. There are 4 available target deletion policies.

  • restrict (default) - Any attempt to delete the target object immediately raises an exception.

  • delete source - when the target of a link is deleted, the source is also deleted. This is useful for implementing cascading deletes.

    There is a limit to the depth of a deletion cascade due to an upstream stack size limitation.

  • allow - the target object is deleted and is removed from the set of the link targets.

  • deferred restrict - any attempt to delete the target object raises an exception at the end of the transaction, unless by that time this object is no longer in the set of link targets.

Source deletion

New

Only available in EdgeDB 2.0 or later.

Source deletion policies determine what action should be taken when the source of a given link is deleted. They are declared with the on source delete clause.

  1. type MessageThread {
  2. property title -> str;
  3. multi link messages -> Message {
  4. on source delete delete target;
  5. }
  6. }
  7. type Message {
  8. property content -> str;
  9. }

Under this policy, deleting a MessageThread will unconditionally delete its messages as well.

To avoid deleting a Message that is linked to by other schema entities, append if orphan.

  1. type MessageThread {
  2. property title -> str;
  3. multi link messages -> Message {
  4. on source delete delete target;
  5. on source delete delete target if orphan;
  6. }
  7. }

Links can have abstract targets, in which case the link is considered polymorphic. Consider the following schema:

  1. abstract type Person {
  2. property name -> str;
  3. }
  4. type Hero extending Person {
  5. # additional fields
  6. }
  7. type Villain extending Person {
  8. # additional fields
  9. }

The abstract type Person has two concrete subtypes: Hero and Villain. Despite being abstract, Person can be used as a link target in concrete object types.

  1. type Movie {
  2. property title -> str;
  3. multi link characters -> Person;
  4. }

In practice, the Movie.characters link can point to a Hero, Villain, or any other non-abstract subtype of Person. For details on how to write queries on such a link, refer to the Polymorphic Queries docs

It’s possible to define abstract links that aren’t tied to a particular source or target. If you’re declaring several links with the same set of properties, annotations, constraints, or indexes, abstract links can be used to eliminate repetitive SDL.

  1. abstract link link_with_strength {
  2. property strength -> float64;
  3. index on (__subject__@strength);
  4. }
  5. type Person {
  6. multi link friends extending link_with_strength -> Person;
  7. }

See also

SDL > Links

DDL > Links

Introspection > Object types