Defining schema

Schema

A TypeDB schema is like a blueprint of a database.

A schema contains all user-defined types and rules that can be used in the database.

The types in a database schema define the data model, its constraints, and the vocabulary used in TypeQL queries to the database.

How to define a schema

To define or undefine anything in a TypeDB database schema we need:

  1. Build the TypeQL query string (see below on this page):

  2. Connect to a TypeDB database with a SCHEMA session.

  3. Run a proper query type (Define/ Undefine) with a query string we built in a WRITE transaction.

  4. Commit the transaction to persist the changes.

Define types

Any number of define statements can be combined in a single Define query, requiring only one define clause with only one define keyword at the very beginning.

To define a type use the following syntax:

define

<label> sub <parent type label>
    [(, abstract)]
    [(, owns <attribute type label> [@annotation])...]
    [(, plays <relation type label>:<role>)...];

The define keyword is used only once per query for any number of statements.

The abstract keyword makes the type abstract.

The owns keyword defines an attribute ownership.

The plays keyword defines a role that this type can play.

See examples
define object sub entity;

In the above example we define the object type as a subtype of the entity type, which is a built-in root type.

Here is more complex example:

define

object sub entity;
resource sub object;
file sub resource,
   owns path,
   owns size-kb,
   plays object-ownership:object;

If we try to run this example in an empty database it will throw an error, because the path and size-kb attribute types we mentioned as owned by the file entity type actually need to exist in the schema.

They can be defined in the schema prior to our query (e.g., if we run this query on the database from the Quickstart page), or we can define them in the same query. To do that, use the following query instead:

define

object sub entity;
resource sub object;
file sub resource,
   owns path,
   owns size-kb,
   plays object-ownership:object;

path sub attribute, value string;
size-kb sub attribute, value long;

object-ownership sub relation,
   relates object;

All types, mentioned in a type definition (owned attributes or relation that the type can play a role in) must exist in the schema or be defined in the same query.

Define entity type

See the Define types section.

No specific syntax for entities.

For more information about entity types see the Entity types section in Type system page.

Define relation type

To define a relation type use the following syntax:

define

<label> sub (<relation type label>)
   [(, abstract)]
   [(, owns <attribute type label> [@annotation])...]
   (, relates <role label>) [(, relates <role label>)...]
   [(, plays <relation type label>:<role>)...];

The relates keyword defines a role of the relation type. There must be at least one role for any relation type.

See example
define

ownership sub relation,
    relates owned,
    relates owner;

group-ownership sub ownership,
    owns ownership-type,
    relates group as owned;

In the above example we define:

  • the ownership type as a subtype of the relation root type, with:

    • owned role,

    • owner role;

  • and the group-ownership type as a subtype of the ownership type, with:

    • ownership-type role,

    • group role, overriding inherited owned role,

    • inherited owner role.

For more information about relation types see the Relation types section in Type system page.

Define attribute type

To define an attribute type use the following syntax:

define

<label> sub (<abstract attribute type label>)
[(, abstract)]
, value <value type> [, regex "<regex-expression>"]
[(, owns <attribute type label> [@annotation])...]
[(, plays <relation type label>:<role>)...];

The value keyword is mandatory and used to define a value type for the attribute.

For more information about attribute types see the Attribute types section in Type system page.

Define rules

To define a rule use the following syntax:

define

rule <rule-label>:
when {
    ## the conditions
} then {
    ## the conclusion
};

Rule label must be unique. Defining a rule with existing label will rewrite the old rule with the new one.

The condition definition goes inside the when clause.

The conclusion definition goes inside the then clause.

For more information about rules see the Define rules page.

Undefine

Undefine query is used to remove a type or a rule definition form a schema.

Any number of undefine statements can be combined in a single Undefine query, requiring only one undefine clause with only one undefine keyword at the very beginning.

Undefine types

To undefine a type use the following syntax:

undefine

<label> sub <parent type label>
    [(, owns <attribute type label> [@annotation])...]
    [(, plays <relation type label>:<role>)...];

The undefine keyword is used only once per query for any number of statements.

The sub keyword is used only to remove the type mentioned left from the keyword from a schema. The parent type label must be a direct or indirect supertype.

The owns keyword undefines an attribute ownership.

The plays keyword undefines a role that this type can play.

See examples

Let’s define a few new types to undefine them later.

define

tag sub attribute, value string;

connection sub relation,
   relates item;

item sub entity,
   owns tag,
   plays connection:item;

In the above example we define the tag attribute type, connection relation type with the item role, and item entity type, that can owns tag attribute type and plays connection:item role.

To undefine an attribute ownership use the following query:

undefine

item owns tag;

To undefine the ability to play the role connection:item use the following query:

undefine

item plays connection:item;

To undefine the item entity type (remove it from the schema) use the following query:

undefine

item sub entity;

To be able to remove a type we need to delete all instances of data and all subtypes of this type first.

The usage of sub keyword in the undefine query statement will remove the type on the left from the sub completely from the schema regardless of any ownerships or roles mentioned for this type.

Undefine rules

To undefine a type use the following syntax:

undefine

rule <rule-label>;

Modification

Modify types

The define statements are idempotent. By sending the same define query twice or more times the very same resulting schema must be achieved as if we send it only once. So types and/or rules will not be duplicated.

We can add ownership of an attribute, annotation to an ownership, or a role to play by just defining the add-on.

See example

Let’s define a new ownership for the item entity.

define

item owns size;

In the query above we define an ownership of size attribute by the item type. For the query to succeed we need both the item and the size types to exist in the schema already.

Rename types

To rename a type (to change its label), use the TypeDB Studio or TypeDB Driver API rename method for a type class object: Java, Python, Node.js.

Modify rules

To modify a rule define a new rule with the same label. It will overwrite the existing rule upon commit.

Learn more

After we define the schema of our database we can try writing and reading data from the database.

In case there is no database schema ready yet, we can use the IAM schema to try all the queries.