Define types
See the Fundamentals page for more information about schema and types.
See the full table of contents for this page
To use a new TypeDB database, we need to define its schema first. We can do it with a Define query.
To define a schema, a |
There is no limitation in the order of types to define. We can define schema types in any order if the schema is valid. TypeDB Clients validate our schema definition requests before sending them to a TypeDB server. We will not be able to commit changes if the resulting schema isn’t valid.
Define queries are idempotent. Running the same define query a second time shall not produce any changes to the database schema. Running a modified version of an already executed schema definition query can add concepts to the schema but mostly can’t modify existing ones. TypeQL schema statements do NOT replace existing type definitions but add missing parts. Two notable exceptions are:
|
Define query
A define query adds new or modifies existing types and/or rules in the database schema.
A define query consists of a single define
clause.
TypeQL define
clause must begin with the define
keyword.
We can run multiple statements as a single query.
The define
keyword must only be included once per query at the beginning.
This page only covers how to define types. For defining rules, see the Define rules page. |
Syntax
Define queries are written in TypeQL with the following syntax:
define <pattern>
The pattern used in the define query is limited to the DDL part of TypeQL as it declares only types (and rules), but not instances of data.
Type definition syntax
This is the generic syntax of the define query for a type definition:
define
<label> sub <supertype labell>
[(, abstract)]
[, value <value-type>]
(, relates <role label>)
[(, relates <role label>)...]
[(, owns <attribute type label> [@annotation])...]
[(, plays <relation type label>:<role>)...];
The line with the value
keyword is relevant only for attribute types definition.
The lines with the relates
keyword are relevant only for relation types definition.
See the specific syntax for entity types, relation types, or attribute types below.
Example
define
credential sub attribute, value string;
full-name sub attribute, value string;
id sub attribute,
abstract,
value string;
email sub id, value string;
subject sub entity,
abstract,
owns credential,
plays group-membership:group-member;
user sub subject,
abstract;
person sub user,
owns full-name,
owns email;
membership sub relation,
abstract,
relates parent,
relates member;
group-membership sub membership,
relates group as parent,
relates group-member as member;
The above example can be run in TypeDB Studio. See the Quickstart guide for full descriptions of the following steps:
-
Make sure a TypeDB server is up.
-
Start TypeDB Studio.
-
Connect TypeDB Studio to the server.
-
Create or select a new database.
-
Open a Project folder.
-
Copy and paste the query code above into a new tab of the Text editor.
-
Ensure the Session type switch is set to "Schema".
-
Ensure the Transaction type switch is set to "Write".
-
Click the green "play" button to start the transaction.
-
Click the "checkmark" button to commit the changes.
After a successful commit, all the types can be seen in the Type Browser panel in the bottom left part of the Studio window.
The following query can be run in a new tab in Schema / Read mode to see the schema visualized as a graph.
match $s sub thing;
get;
As the result of the above query TypeDB Studio should display a graph visualization of the schema defined earlier.

The Consider using For example: Data retrieval example
|
In the following sections, we can find more detailed information on different schema definition queries and possibilities.
Define entity types
Overview
Entity types are defined independently of other types, but may subtype other entity types.
Optionally, entity types can:
-
Be abstract.
-
Own attribute types.
-
Play roles defined in relation types.
Syntax
Entity types are defined in TypeQL with the following pattern:
<label> sub (entity | <entity type label>) [(, abstract)]
[(, owns <attribute type label> [@annotation])...]
[(, plays <relation type label>:<role>)...];
Examples
Basic
The following define
query creates a new entity type, object
, by subtyping the entity
built-in type.
define
object sub entity;
Abstract
Optionally, types can be defined as abstract
. An abstract type can’t be instantiated and must be
subtyped in order to create entities. It exists only so other types can inherit ownerships over attribute types it
owns and the roles it plays. We can use abstract types in queries, expecting to retrieve instances of its concrete
subtypes.
define
object sub entity,
abstract;
Owns an attribute
To define a new entity type that owns one or more attribute types, use the owns
keyword followed by the label of the
attribute type. The attribute types are appended to the entity type definition with commas. Note, attribute types must
be defined before or concurrently (in the same query) with its owner(s). We can add owners later, but we can’t
own nonexistent attribute types.
define
object-type sub attribute, value string;
object sub entity,
abstract,
owns object-type;
Cardinality
By default, an entity can have multiple attributes of the same type: zero, one, or many.
By having multiple attributes of the same type we’re effectively creating a multivalued attribute (as if having an attribute type instantiated with multiple values).
Use the @key
keyword to limit the cardinality to exactly one and add uniqueness constraint.
Hence, the instance of the type with key ownership will have exactly one (no more and no less)
key attribute instance.
See the example in the Key attribute section.
Plays a role
To add roles that entities of a specific entity type can play, use the plays
keyword.
define
access sub relation,
relates object;
object sub entity,
abstract,
plays access:object;
Subtypes another entity
All types that are subtyping |
An entity type can subtype another entity type by using the same sub
keyword, but replacing the entity
keyword
after it with a label of another entity type to subtype.
define
path sub attribute, value string;
object sub entity,
abstract,
owns object-type,
plays access:object;
resource sub object,
abstract;
file sub resource,
owns path;
In the above example, the resource
and file
entity types are subtypes of the object
, which itself is a subtype
of the entity
built-in type. They inherit the object-type
attribute type ownership from it as well as its
access:object
role. However, while the resource
subtype is abstract, the file
subtype is not. Hence, we
can create file
entities, but not resource
entities.
Further, the path
attribute type will only be owned by the file
entity type and any other entity types which
subtype it or directly define ownership.
Overrides inherited attribute ownership
To override an inherited ownership use owns
keyword with the new attribute type label, followed by the as
keyword
and the inherited attribute type label. For example:
define file sub resource, owns file-type as object-type;
The new attribute type that overrides inherited type is defined in the schema as subtype of the inherited attribute type. Hence, the inherited attribute type is abstract and has the same value type as the new attribute type. The example above in a schema would look like this:
define
path sub attribute, value string;
object-type sub attribute, abstract, value string;
file-type sub object-type, value string;
object sub entity,
abstract,
owns object-type;
resource sub object,
abstract;
file sub resource,
owns path,
owns file-type as object-type;
In the above example, the file
entity type owns the path
and file-type
attribute types, with the file-type
attribute type overriding the inherited object-type
attribute type.
Define relation types
Overview
Relation types are defined independently of other types but may subtype other relation types. They can be abstract. Their definition can include ownership of attribute types, roles other types play within them, and roles they can play in other relation types:
-
Owned attribute types are added with the
owns
keyword followed by the attribute type label. -
Its own roles are added with the
relates
keyword followed by the role label. At least one role must be defined for any relation. -
Roles it can play in other relations are added with the
plays
keyword followed by the relation type label and role.
Syntax
Relation types are defined in TypeQL with the following pattern:
<label> sub (relation | <relation type label>) [(, abstract)]
[(, owns <attribute type label> [@annotation])...]
(, relates <role label>)
[(, relates <role label>)...]
[(, plays <relation type label>:<role>)...];
Examples
Basic
The following statement creates an access
relation that defines two roles:
-
object
— played by instances of theobject
entity type or its subtypes (e.g.,file
). -
action
— played by instances of theaction
entity type.
define
access sub relation,
relates object,
relates action;
Plays a role
In addition to defining its own roles played by other types, a relation type can play roles in other relation types.
define
access sub relation,
relates object,
relates action,
plays permission:access,
plays change-request:change;
In the above example, access
relation type can play the access
role in permission
relation type and
the change
role in change-request
relation type. Besides, an access
relation type relates an
object
role (e.g., file) and a action
role (e.g., read). Thus, a permission
relation type relates
the access
(i.e., read + file) and a subject
(e.g., person
with full-name
attribute Kevin Morrison
).
Defines multiple roles
A relation can define multiple roles (from one to many).
define
change-request sub relation,
relates change,
relates requestee,
relates requester;
Owns an attribute
A relation type can own zero, one, or many attribute types.
define
segregation-policy sub relation,
relates action,
plays segregation-violation:policy,
owns name;
Abstract
Optionally, relation types can be defined as abstract
, so they must be subtyped in order to create instances. An
abstract relation type exists only so other relation types can inherit the attribute types it owns and the roles it
defines and plays.
define
violation sub relation,
abstract,
owns name;
Subtypes another relation
A relation type can subtype another relation type by replacing the relation
keyword with the label of another
relation type. The subtype will inherit all owned attribute types and all roles related or played by the parent type.
define
membership sub relation,
relates parent,
relates member;
collection-membership sub membership;
In the example above, the collection-membership
relation type inherits the parent
and member
roles defined in
its parent type: membership
.
Overrides a role
The labels of the inherited roles can be overridden to distinguish between the roles inherited by a relation subtype versus the roles defined by its parent type.
define
membership sub relation,
relates parent,
relates member;
collection-membership sub membership,
relates collection as parent;
In the example above, the collection-membership
relation type subtypes the membership
relation type and overrides
the inherited parent
role as collection
. The inherited member
role is inherited as it is.
The two examples above can be run one after another. The second one will update the |
By overriding an inherited role, we implicitly prevent the sub-relation from relating the role that would otherwise be inherited. |
Complex example
define
ownership sub relation,
relates owned,
relates owner;
group-ownership sub ownership,
relates group as owned,
owns ownership-type;
object-ownership sub ownership,
relates object as owned,
owns ownership-type;
access sub relation,
relates object,
relates action,
plays change-request:change;
change-request sub relation,
relates requester,
relates requestee,
relates change;
The example above defines one attribute type and five relation types:
-
ownership
— subtypes therelation
built-in type, and relatesowned
, andowner
roles. -
group-ownership
— subtypesownership
relation type, relatesgroup
asowned
, andowner
(inherited). -
object-ownership
— subtypesownership
relation, relatesobject
asowned
, andowner
(inherited). -
access
— subtypes therelation
built-in type, relatesobject
(e.g., file) andaction
(e.g., read), plays the role ofchange
inchange-request
relation type. -
change-request
— subtypes therelation
built-in type, relatesrequester
,requestee
andchange
.
Define attribute types
Overview
Attribute types are defined independently of other types, but may subtype a user-defined abstract attribute type. Any type can have an ownership over any attribute type.
Attributes owning an attributes feature will be deprecated in one of the upcoming versions and deleted in TypeDB version 3.0. |
Attributes playing a role in a relation feature will be deprecated in one of the upcoming versions and deleted in TypeDB version 3.0. |
Optionally, attribute types can:
-
Be abstract.
-
Own other attribute types (this will be deprecated).
-
Play roles in relations (this will be deprecated).
Syntax
Attribute types are defined in TypeQL with the following pattern:
<label> sub (attribute | <abstract attribute type label>) [(, abstract)], value <value type> [, regex "<regex-expression>"]
[(, owns <attribute type label> [@annotation])...]
[(, plays <relation type label>:<role>)...];
The following value types are supported:
-
long
— a 64-bit signed integer -
double
— a double-precision floating point number, including a decimal point -
string
— enclosed in double"
or single'
quotes -
boolean
—true
orfalse
-
datetime
— a date or date-time in the following formats:-
yyyy-mm-dd
-
yyyy-mm-ddThh:mm
-
yyyy-mm-ddThh:mm:ss
-
yyyy-mm-ddThh:mm:ss.f
-
yyyy-mm-ddThh:mm:ss.ff
-
yyyy-mm-ddThh:mm:ss.fff
-
Examples
Basic
define
name sub attribute, value string;
email sub attribute, value string;
ownership-type sub attribute, value string;
review-date sub attribute, value datetime;
validity sub attribute, value boolean;
Subtypes another attribute type
An attribute type can subtype another attribute type if its abstract. This is useful when the possible values of an attribute type can be categorized, and applications can benefit from querying entities and relations not only by a value of an attribute but also by a label of attribute type.
An attribute type can only subtype an abstract attribute type. However, the subtype of an attribute type can itself be abstract. Further, an attribute subtype must have the same value type as its parent attribute type. Note, the value type of an attribute subtype can be omitted in its definition. It will be inherited from its parent attribute type. |
define
id sub attribute, abstract, value string;
email sub id, value string;
name sub id, value string;
path sub id, value string;
number sub id, value string;
The above example creates an attribute type, id
. However, because different entities can be identified by different
information, the id
type is subtyped by email
, name
, path
, and number
types — making it possible to query
users by email
, business units by name
, files by path
and records by number
.
Unique attribute annotation
Use the @unique
keyword to add uniqueness constraint to the ownership of an attribute.
This prevents two instances of the same type from owning the same attribute instance (with the same value).
define
object-type sub attribute, value string;
object sub entity,
abstract,
owns object-type @unique;
The |
Unique annotation can be inherited, even using override of an ownership.
See example
define
organisation sub entity,
abstract,
owns organisation-id @unique;
organisation-id sub attribute, abstract, value string;
non-profit sub organisation,
owns nonprofit-id as organisation-id;
nonprofit-id sub organisation-id, value string;
In this example non-profit
owns nonprofit-id
with unique constraint. It’s inherited from organizatrion-id
.
Key attribute annotation
Use the @key
keyword to set the owned attribute as key.
That limits the cardinality to exactly one and adds uniqueness constraint.
Hence, the instance of the type with attribute ownership with @key
annotation will have exactly one
(no more and no less) key attribute instance, and it will be unique for all instances of the same type.
define
object-type sub attribute, value string;
object sub entity,
abstract,
owns object-type @key;
An ownership can’t have both |
Regular expressions
The values of an attribute type can be restricted using Java regular expressions. For example, to constrain it to a set of options.
define
visibility sub attribute, value string, regex "^(public|private|closed)$";
The above example defines an attribute type: visibility
. It is intended for user groups, and specifies a regex to
restrict its values to public
, private
and closed
.
Owns other attribute types
While it is more common for entity and relation types to own attributes, attribute types can also own (other) attribute types.
Attributes owning an attributes feature will be deprecated in one of the upcoming versions and deleted in TypeDB version 3.0. |
define
symlink sub attribute, value string;
filepath sub attribute,
value string,
owns symlink;
The above example creates an attribute type filepath
, intended for files. It is assumed there can be multiple copies
of a file
, each with its own filepath
— and symlinks can be created that point to these filepaths. Thus, the
filepath
attribute type (and NOT the file
entity type) owns the symlink
attribute type.
Plays a role
While it is more common for the roles in relations to be played by entities or other relations, they can also be played by attributes.
Attributes playing a role in a relation feature will be deprecated in one of the upcoming versions and deleted in TypeDB version 3.0. |
define
credential sub attribute,
value string,
plays change-request:change;
The above example creates the credential
attribute type, and specifies it can play the role of change
in
the change-request
relation type. While change-requests
were intended to manage access changes, they can now be
used to manage credential
changes as well.