Lesson 7: Understanding query patterns

Patterns as constraints

  • A pattern comprises a conjunction of any number of consecutive statements.

  • A pattern is equivalent to a list of constraints about the terms involved, which must be simultaneously satisfied. A term can be either a variable or a literal.

  • Type inference determines the type of each variable by solving the pattern as a constraint satisfaction problem.

  • If a variable in a query pattern has no possible types, the pattern fails validation and an exception is thrown.

Relation patterns

  • A relation with any number of role players can be represented using a relation tuple with the same number of elements. This allows for unary, binary, ternary, and n-ary relations.

    n-ary-relation (role-1: $a, role-2: $b, role-3: $c, role-4: $d, ...);
  • role players can be omitted from relation tuples, allowing partial tuple representations of relations. This will match those relations regardless of the omitted role players.

    ternary-relation (role-1: $a, role-2: $b);
  • Roles can be omitted from relation tuples, allowing TypeDB to use role inference to infer them. This will match the role players in any combination of the relation’s roles.

    example-relation ($a, $b);
  • A relation’s type can be omitted after a relation tuple, allowing TypeDB to use type inference to infer the possible types. This will match any relations with the supplied role names.

    (role-1: $a, role-2: $b);

Logical operators

  • A disjunction of patterns is made by placing those patterns in separate blocks interleaved with the or keyword, terminated with a ; delimiter.

    {
        # branch 1
    } or {
        # branch 2
    };
  • A negation of a pattern is made by placing it in a block preceded by the not keyword and followed by a ; delimiter.

    not {
        # negated pattern
    };
  • An optional pattern of a pattern is made by placing it in a block preceded by the try keyword and followed by a ; delimiter. Optionals let you do partial matching:

    try {
        # optional pattern
    };
  • An is statement is used to specify that two variables represent the same data object.

    $a is $b;

Value comparisons

  • The equality operators == and != are used to compare values of all types.

    $attribute-1 == $attribute-2;
  • The ordering operators >, >=, <, and <= are used to compare values of all types.

    $attribute-1 > $attribute-2;
  • The contains operator is used to specify that one string contains another string in a case-insensitive manner.

    $string contains "sub-string";
  • The like operator is used to specify that a string matches a Regex.

    $string like "^regex pattern$";

Value expressions

  • The assignment operator let $var = <expression> is used to specify the value of a computed variable.

  • The assignment iterator let $var in <expression> is used to specify the value of a of iterating over a computed iterable, one at a time

  • Numeric values can be computed using arithmetic operators ^, *, /, %, +, and -, as well as arithmetic functions min, max, round, floor, ceil, and abs inside expressions

Solution set semantics

  • If a query pattern can be split into multiple independent sub-patterns with no shared variables, then those sub-patterns are resolved against the schema independently, and all possible combinations of data matching each sub-pattern are returned.

  • If the constraints on two variables are identical, then each pair of data instances matched by those variables will be returned twice.

  • These behaviours can lead to unintended query results if not accounted for.

Further learning

Learn how to structure query results in the optimal manner, covering result grouping, aggregations, sorting, and pagination.

Learn how to design schemas for TypeDB using the conceptual PERA model, including common design patterns and pitfalls.

Read the TypeQL patterns reference, covering conjunctions, disjunctions, negations, and pattern matching behaviour.