Match clause

A match clause seeks data in a TypeDB database. It can be used only as a part of a query with another clause to specify how to use matched data.

It’s a very important clause as it can be used in all data queries to match existing data from a database for a subsequent retrieval or processing.

Behavior

A match clause is used to find all existing concepts in a database that satisfy a pattern.

Every matched result of a match clause contains a concept for every concept variable and a value for every value variable used in a given pattern. Those concepts and values are used in a subsequent clause of the same query by their variables.

You can’t use a Fetch, Get, Delete, or Update query without a match clause at the beginning. To retrieve or delete some data from a database, we need to specify the data first.

The only data query that can be used without a match is an Insert, as you can insert completely new data without matching something in a database first.

You can think of matching a pattern as solving a system of equations, where every equation is a single statement in a pattern. TypeDB solves the system and returns all its solutions, including permutations.

Syntax

Match clauses are written in TypeQL with the following syntax:

match <pattern>

A match clause can use all existing patterns that are valid, according to a schema. A pattern used in a match clause can address both schema types and data instances.

Match clause results

A match clause returns a set of matched results. Every matched result is a solution for a given pattern, i.e., it makes that pattern a true statement, based on database’s data and schema.

The number of results found (and returned) can be zero (no solutions found), one, or multiple. There can be no duplicates because results are naturally deduplicated in a set.

Consider the following example:

Pattern example
match
$p isa person, has full-name $fn;

The above example contains a pattern for an instance of person type having a full-name attribute. If there is a person with no full-name attributes in a database, then such a person will not get into results. If there is a person with two full-name attributes, then such a person will be mentioned in two results: one for each full-name.

A match clause returns all possible solutions for a given pattern, including all possible permutations.

Data queries use results of a match clause to retrieve or process data. The second clause of a data query is executed once for every matched result. If there are no matched results, there will be no data inserted/deleted/retrieved. If there are two matched results, the subsequent clause will be executed twice, inserting/deleting/retrieving data every time. An insert query without a match clause is executed exactly once.

Variables

Variables can be used in data queries and rules to reference a concept. Variables mentioned in a match clause are included in its results. All variables of a query must be bound in a match clause of a data query or in a condition of a rule.

There are two types of variables:

A concept variable starts with the dollar sign $ followed by a variable label (for example, $x) and references exactly one concept (type or data) per every result (solution) matched for a pattern.

A value variable starts with question mark ? followed by variable label (for example, ?x) and references exactly one value per every result (solution) matched for a pattern. See Value variables below.

Patterns overview

A pattern is a set of statements combined by an implicit conjunction (logical "AND"). Hence, patterns are composable, meaning you can combine two patterns by joining their statements together in a new pattern.

Statements declare constraints for types and data. They consist of variables, keywords, types, and values. All statements must end with a semicolon.

Most simple statements consist of a subject, predicate, and an object in that particular order. Some predicates, like abstract don’t have a subsequent object. There are predicates for schema types and data instances. They are used in schema statements and data statements respectively. See below an example of simnple statements that describe a person, that has the specified full-name and specified email.

Simple statements example
$p isa person;
$p has full-name "Bob";
$p has email "bob@gmail.com";

The above example consists of three simple statements about the same subject, represented by the variable $p:

  • It is an instance of a type person;

  • It has an attribute of type full-name and value Bob;

  • It has an attribute of type email and value bob@gmail.com;

Multiple simple statements with the same subject can be combined to a complex statement, consisting of a single subject, and multiple comma-separated pairs of predicates and objects.

Complex statement example
$p isa person, has full-name "Bob", has email "bob@gmail.com";

The above example combines simple statements from the previous example and achieves the same result without repeating the subject ($p).

Note that the patterns above use the same schema that is used in the Quickstart guide. That schema defines types, used in the patterns: person, full-name, and email.

In a data query, you can use variables for any type, instance of a type, or value; and a subject is usually a concept variable.

In a match clause we can use both Data statements and Type statements, as well as Negation and Disjunction. For example, see the Combined example section at the end of this page.

Data statements

Data statements are used for manipulating data instances. They can be used only in data queries and rules.

Data statements
Statement name Syntax Examples

Instance of a type or a subtype

<var> isa <type>;

$p isa person;

Instance of a type

<var> isa! <type>;

$p isa! person;

Instance of an attribute type

  • <var> [<value>] isa[!] <attr-type>;

  • <var> contains <value>;

  • <var> like <regex>;

  • <var> > <value>;

  • $a "Kevin Morrison" isa full-name;

  • $b contains "Kevin";

  • $c like "(Masako Holley|Kevin Morrison)";

  • $d > 4;

Instance of a relation

[<var>] ([<role>:] <var> [, [<role>:] <var>]) isa <relation-type>;

  • $pe (subject: $p, access: $ac) isa permission;

  • ($p,$ac) isa permission;

Ownership

has <attr-type> (<var> | [<comparison-operator>] <value>);

$f has size-kb > 300;

Comparison

<var> [<comparison-operator>] <value>;

$a > 300;

Equality

<var1> is <var2>;

$t is $p;

Expression computation

<value-var> = <expression>;

?x = round($s / 10);

For more information on Comparison operators and Computation, see the sections below.

Type statements

Type statements are used for schema types. They can be used only in a match and define clauses. For define clause patterns examples, see the Type definitions page.

Type statements
Statement name Syntax Example

Type

<var> type <type>;

$t type person;

Type or subtype

<var> sub <type>|<var>;

$t sub subject;

Direct subtype

<var> sub! <type>|<var>;

$t sub! subject;

Role in a relation type

<var> relates <role>|<var>;

$rel relates subject;

Role player type in a relation

<var> plays <relation>:<role>|<var>;

$r plays permission:subject;

Owner type of an attribute type

<var> owns <attr-type>|<var>;

$o owns full-name;

Attribute subtype

<var> sub[!] <attribute-type>|<var> [, value <value-type>];

$s sub id, value string;

Negation

Use negation to exclude some concepts from a result.

The intuitive meaning of a negated statement is that of a complement. However, a relation complement is not clearly defined. We understand statement negation in terms of computation of set differences. The set-difference semantics is different to the perhaps familiar semantics of Negation-as-Failure of Prolog.

To use negation, employ the following syntax:

not {<negated_pattern>};

See an example below.

Negation example
$p isa person, as full-name $fn;
not {$fn contains "Kevin";};

We can use multiple statements inside a negation block.

At least one variable in a negation block must be bound to a statement outside of negation. This ensures that set-difference operations are performed on sets that are not disjointed. Variables declared in negation blocks are local to the block they are defined in.

Rules conditions with negation can’t contradict themselves (to prevent infinite recursion).

Disjunction

Use disjunction to add some variability to possible solutions. To satisfy a match, at least one statement must be matched.

To use disjunction, employ the following syntax:

{<pattern1>} or {<pattern2>};

See an example below.

Disjunction example
$p isa $t;
{$t type person;} or {$t type file;};

We can use multiple statements inside a disjunctive branch. Variables that are used only in a disjunctive block will not be returned in results of a match clause. See an example below.

Disjunction example with extra variables
$p isa $t;
{$t type person; $p has full-name $f;} or {$t type file; $p has path $path;};

Computation

You can use and process primitive numeric values in a query with the help of Value variables, Arithmetic operations, and other Built-in functions.

Value variables

Value variables are used in patterns with computation to represent exact values in statements. These variables are never materialized permanently and are only used within the scope of a particular query or rule.

To persist a value of a value variable, you can save it into a database by using an attribute type with a matching value type. Value variables can be one of the following value types (the same as value types for attributes):

  • long — a 64-bit signed integer number

  • double — a double-precision floating point number, including a decimal point

  • string — a string enclosed in double " or single ' quotes

  • boolean — a true or false

  • datetime — a date or date-time in one of 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

To assign a value for a value variable, use the = sign:

Value variable example
$r isa radius;
?s = 3.14 * $r^2;

A statement starting with a value variable and an equals sign is called value assignment statement. The part to the right from equals sign in a value assignment operator is an expression.

An expression describes a computation of a value for a value variable. While a value variable can be used in any clause of a data query, an expression can be used only in a match clause or condition of a rule. It contains any combination of the following elements:

Expression example
$s isa size-kb;
?x = round($s/2) + 1;

The above pattern matches all instances of data for the size-kb attribute type bounding them to the $s concept variable. The value variable ?x is bound to the value of $s divided by 2, rounded, and then added 1. Hence, every matched result for this pattern consists of an attribute in $s and its processed value in ?x.

Comparison operators

The following operators are supported for comparing values: ==, !=, >, >=, <, and <=.

In TypeDB version 2.18.0, the single equals sign (=) was deprecated as a comparison operator. Now it can be used to assign a value to a value variable. While in TypeDB 2.x it is possible to use it as a comparator for backward compatibility, we recommend using == for equality instead.

Arithmetic operations

The following keywords can be used for arithmetic operations between value variables, concept variables referencing attributes, and constants:

  1. () — parentheses. See an example.

  2. ^ — exponentiation (power). See an example.

  3. * — multiplication. See an example.

  4. / — division. See an example.

  5. % — modulo. Returns the remainder of a division. See an example.

  6. + — addition. See an example.

  7. - — subtraction. See an example.

The above list is sorted by the order in which those operations are applied in an expression.

Arithmetic example
$f isa file, has size-kb $s;
?mb = $s/1024;
?mb > 1;

In the above example, we designed a pattern to match instances of data for file type owning size-kb attribute with a value that, after dividing it by 1024 (to get megabytes out of kilobytes), is bigger than 1.

Built-in functions

Built-in functions are usually invoked with adjacent parentheses that contain arguments to apply the function. Those arguments are separated by a comma as a separator. The following built-in functions are available in TypeDB:

  • min — the minimum of the arguments. See example.

  • max — the maximum of the arguments. See example.

  • floor — the floor function (rounding down). See example.

  • ceil — the ceiling function (rounding up). See example.

  • round — the default (half-way up) rounding function. See example.

  • abs — the modulus (or absolute value) function. See example.

Combining statements

By combining statements from different patterns and using disjunction and negation, you can express patterns to match very specific data. See the Combined example below.

Combined example

Combined example

The above pattern is a combination (conjunction) of statements from multiple patterns:

  1. Conjunction 1 specifies the variables for two person instances, their full-names, action instance, and file instance that has path README.md.

  2. Disjunction specifies that the actions of interest are either modify_file or view_file.

  3. Negation 1 specifies that person $p1 shall not have full-name with value of Masako Holley.

  4. Negation 2 specifies that person $p2 shall not have full-name with value of Masako Holley.

  5. Conjunction 2 specifies that the file has access with the action that was specified earlier, and both instances of the person to have the permission to the specified access.

In short, the above example matches pairs of people who both have permission to access the same file with a path of README.md. The pattern additionally specifies the access to be either modify_file or view_file, and neither people to have the full-name attribute with the value Masako Holley.

Learn more

A match query can be used in any data query: Fetch, Get, Insert, Delete, or Update.

For additional examples of using patterns in different queries, see the Patterns and queries examples page.

Provide Feedback