Queries as Functions
TypeQL function provides a way to create abstractions over existing data,
allowing queries to be expressed at a higher level.
They can live in your schema - as a "library" your database provides,
or be specified in the preamble of a query using the with
keyword.
A function accepts a tuple of concepts as arguments, and returns zero or more tuples of concepts as a result. The body of a function can be a pipeline consisting of any number of read stages.
fun mutual_friends($p1: person, $p2: person) -> { person }:
match
$f1 isa friendship, links (friend: $p1, friend: $pm);
$f2 isa friendship, links (friend: $p2, friend: $pm);
return { $p2 };
Arguments & returns
Function arguments & returns can be instances or values, but not types. The types of these concepts must be declared in the signature.
fun divide($dividend: integer, $divisor:integer) -> integer, integer:
match ...
return first $quotient, $divisor;
A function can either return a single tuple of concepts, or a stream of tuples.
For a stream return, the declaration is surrounded by curly braces {…}
.
As in the example above, a function returning a single tuple must convert
the stream output of the pipeline to a single tuple using either the first
or the last
modifiers.
Reduce returns
Functions can also return an aggregation over the stream output by the body, using the reduce return modifier.
fun post_count($page: page) -> { integer }:
match
$posting isa posting, links (posted: $page);
return count($post);
Since |
Cyclic functions & tabling
TypeDB tables recursive functions to break cycles. This has implications on the best way to implement the recursion. The classic example is computing the transitive closure of a function. In a tabled setting, the following (left-recursive) formulation is more efficient.
fun reachable($from: node) -> { node }:
match
{ # Base case
$_ isa edge, links (from: $from, to: $to);
} or { # Recursive case
let $mid in reachable($from);
$_ isa edge, links (from: $mid, to: $to);
};
return { $to };
This will return `node`s in a breadth-first fashion.