Officially out now: The TypeDB 3.0 Roadmap >>

Defining types

This page explains how to define types and type traits in TypeDB schemas.

Schema definition queries

All schema (un)definitions in TypeDB are run in schema transactions. There are three kinds of schema definition queries:

  • define <statements>. A define query defines types and their traits, subtyping, as well as more specific annotations on those statements.

  • undefine <statements>. An undefine query can be used to remove definitions of type, their traits, subtyping, and statement annotations.

  • redefine <statement>. A redefine query can be used to change a single statement at a time, overwriting any analogous previously defined statement.

Entity types

Entity types are first defined using the entity keyword.

define entity user;

Subtypes of entity types are always entity types themselves, and can be introduced using the sub keyword.

define entity admin sub user;

Traits of entity types are defined as before using the plays and owns keywords.

Relation types

Relation types are first defined using the relation keyword.

define
  relation friendship,
    relates friend @card(2);

Here, @card(2) is an example of annotation, specifying that there will be exactly two friends in each friendship relation. Without this annotation the role cardinality would default to @card(0..1) (allowing between 0 and 1 friend). See annotations for more.

Subtypes of relation types are always relation types themselves, and can be introduced using the sub keyword.

  • Relation subtypes can specialize the roles of their supertype using the as keyword.

  • Otherwise, if a role is not specialized, relations subtypes automatically inherit that role.

For example

define
  relation close-friendship sub friendship; # inherits friend role
  relation best-friendship sub friendship, # specializes friend role
    relates best-friend as friend @card(1),
    relates other-friend as friend @card(1);

This defines “close friendship” and “best-friendship” relations as a subtype of our friendship relations above.

Note that unlike friendship relations, the subtype of best-friendships contains asymmetric relations (indeed, unfortunately, if A is the best friend of B this need not imply that B is the best friend of A). In general, a single role can be specialized into any number of roles, as long as role cardinalities are compatible.

In the above example, the cardinality annotations @card(1) can be omitted, as they can be inferred by the model checker.

Traits of relation types are defined as before using the plays and owns keywords.

Attribute types

Attribute types are first defined using the attribute keyword, and they must be supplied with a value type using the value keyword (unless, they are annotated as being @abstract, see annotations)

define
  attribute id,
    value string;

Subtypes of attributes types are always attributes types themselves, and inherit the value type of its supertype (if set; otherwise, a new value type can be set). For example:

define
  attribute comment-id sub id;

Recall that attributes do not play roles or own other attributes.

Undefining definitions

Any of the above statements can be undefined. For example

undefine entity admin;

will completely remove the admin from your schema, and with it all traits of the admin type.

Removing a type from your schema will, in general, only succeed if there are no data instance in the type and no other definitions depend on the type (i.e., the type appears neither in another type’s trait nor as another type’s supertype).

If we instead write

undefine sub user from admin;

then this removes admin having user as its supertype, but it does not remove the type admin itself.

Similarly, writing

undefine plays friendship:friend from user;

removes the friend trait from the user type, but leaves the type itself intact. And

undefine owns username from user;

removes the trait of owning usernames.

Redefining definitions

TypeDB also allows concise redefinitions of single statements. For example, after we define

define
  entity user;
  entity admin sub user;
  entity superuser sub user;

we may redefine:

redefine admin sub superuser;

This will turn the initial tree-like type hierarchy into a linear type hierarchy, where admin < superuser < user.

Re-define semantics are the most complex of all three definition queries. However, the simple key property of redefine is: after a successful redefinition, the re-defined statement holds fully, replacing any conflicting prior statement.

While both define and undefine can be following by multiple statements, redefine can be followed by only a single statements. The reason for this is that the order of redefinitions may affect the resulting model; by working with single statements, we avoid this ambiguity.