joins
Table of Contents
Functions
- buildJoinSubquery() : string
- Builds the inner AQL join sub-query body — everything a join `LET` wraps, WITHOUT the enclosing `LET name = ( … )`.
- buildJoinVariable() : string
- Builds a single AQL 'LET' subquery string for a specific join relation.
- buildJoinVariables() : string
- Generates a string of multiple AQL 'LET' statements for all defined joins variables.
- buildPolymorphicJoinVariable() : string
- Builds a single AQL 'LET' subquery for a *polymorphic* join — a join whose target collection is chosen at query time from a discriminator field of the parent document.
- sortJoinVariable() : string
- Generates the internal AQL 'SORT' clause for a join variable subquery.
Functions
buildJoinSubquery()
Builds the inner AQL join sub-query body — everything a join `LET` wraps, WITHOUT the enclosing `LET name = ( … )`.
buildJoinSubquery(string|null $name[, array<string|int, mixed> $definition = [] ][, string $docRef = AQL::DOC ][, ContainerInterface|null $container = null ][, array<string|int, mixed> $init = [] ][, bool $isArray = false ][, array<string|int, mixed> $extraConditions = [] ][, string|null $keyPath = null ]) : string
The returned string is the compiled body:
FOR doc_join IN collection [<nested LETs>] FILTER … [SORT …] RETURN …
buildJoinVariable() wraps it into LET name = ( … ) for a regular
join, while buildPolymorphicJoinVariable() wraps several such bodies
into a single APPEND( ( … ) , ( … ) ) array so the collection can vary
with a discriminator field.
Extracting this body from buildJoinVariable() lets a polymorphic join
reuse the whole join machinery (filtering, sorting, skinning, nested edges /
joins, definition-level gating) per branch. The only addition over the
historical logic is $extraConditions, a list of ready-made AQL predicates
(typically the discriminator guard) prepended to the branch filter.
Arango::CONDITIONS — restricting which joined documents are kept
The definition may carry extra predicates, appended to the key match. Two shapes: a plain array of AQL predicate strings, or — the useful one — a callable returning such an array. The callable receives three arguments, always:
Arango::CONDITIONS => fn( string $join , string $parent , array $init ) :array =>
[ $join . '.active == true' ] ,
$join— the generated loop variable (arandomKey, so it cannot be hardcoded);$parent— the enclosing document reference, to compare against the parent;$init— the request-level init. Contractual keys only:Arango::AUTHORIZER,AQL::SKINandArango::BINDS; the rest is internal.
Declare only the parameters you need. PHP discards the surplus handed to a userland callable, so a one- or two-parameter closure keeps working untouched. An object method or an invokable is accepted too.
Returning [] emits no predicate, which is how a scope stays inert outside an
HTTP request (a CLI run has no authorizer): the query is then byte-for-byte the
unrestricted one, and no bind is required. A non-array return raises.
⚠️ A bind referenced as text inside a predicate (… NOT IN @hidden) cannot be
discovered by the optional-bind pruning of prepareAndExecute(), which looks for
aqlBindRef() objects. If a skin can drop this join, name that bind explicitly in
the 4th argument of prepareAndExecute(), or ArangoDB rejects the whole query.
Parameters
- $name : string|null
-
The logical name of the join relation — used to skin the projection and to prefix the generated variable names of nested relations. Also the default parent key path when
$keyPathis null. - $definition : array<string|int, mixed> = []
-
Configuration array for the join — same keys as buildJoinVariable() (
AQL::MODEL,AQL::FIELDS,Arango::KEY,Arango::PROPERTY,Arango::CONDITIONS, …). - $docRef : string = AQL::DOC
-
The AQL variable name of the main document reference.
- $container : ContainerInterface|null = null
-
Optional DI container used to resolve models.
- $init : array<string|int, mixed> = []
-
Optional associative array used for variable initialization.
- $isArray : bool = false
-
If true, the join key is treated as an array of keys (
IN). - $extraConditions : array<string|int, mixed> = []
-
Ready-made AQL predicate strings prepended to the branch filter, right after the key match (e.g. the discriminator guard of a polymorphic join).
- $keyPath : string|null = null
-
The parent key path used to match the join, absolute from
$docRef(e.g.selector.providerId→doc.selector.providerId). Null falls back on$name, keeping the historical "output name = key path" behaviour. Decoupling it from$nameletsArango::SOURCEanchor the key elsewhere and keeps nested-variable prefixes free of the (possibly dotted) key path. A polymorphic branch passes the shared key path here.
Tags
Return values
string —The compiled join sub-query body (no LET, no enclosing parentheses).
buildJoinVariable()
Builds a single AQL 'LET' subquery string for a specific join relation.
buildJoinVariable(string|null $name[, array<string|int, mixed> $definition = [] ][, string $docRef = AQL::DOC ][, ContainerInterface|null $container = null ][, array<string|int, mixed> $init = [] ][, bool $isArray = false ]) : string
This method generates a complete subquery, enclosed in parentheses, which is assigned to a 'LET' variable. It handles:
- Filtering based on the document keys or custom conditions
- Sorting (if $isArray is true)
- Nested edges and joins
- Field selection and skinning
The subquery body itself is produced by buildJoinSubquery(); this
wrapper only resolves the LET variable name and parenthesizes the body.
Example output:
LET myJoinVar = (
FOR doc_join IN @@collection
FILTER doc_join._key == doc.relatedKey
RETURN { _key: doc_join._key, name: doc_join.name }
)
Parameters
- $name : string|null
-
The logical name for this variable (e.g., 'friends', 'subsidiaries'). Used as the AQL 'LET' variable name.
- $definition : array<string|int, mixed> = []
-
Configuration array for the join. Possible keys:
AQL::MODEL(string) The Documents model class to query.AQL::UNIQUE(string|null) Optional AQL variable name, overrides $name.AQL::FIELDS(array|null) Array of fields to include in the result.AQL::EDGES(array) Array of nested edge definitions.AQL::JOINS(array) Array of nested join definitions.AQL::SKIN(string|null) Optional 'skin' name for field selection.Arango::KEY(string) The key property of the document to match (default Schema::_KEY).Arango::SOURCE(string|null) Optional absolute key path, read from the main document, that anchors the join match (e.g.selector.providerId→doc.selector.providerId). Decoupled from the output field name; defaults to$name.Arango::PROPERTY(string|array|null) Optional property appended, relative to the key path, to the join key.Arango::SORT(string|array|null) Optional sort definition when $isArray is true.Arango::CONDITIONS(callable|array|null) Optional filter conditions: - If array, it must be a list of AQL filter expressions. - If callable, it receives one or two arguments: 1.$docJoin(string) – the join document variable name 2.$docRef(string, optional) – the main document variable name - Must return an array of AQL filter expressions.
- $docRef : string = AQL::DOC
-
The AQL variable name of the main document reference (default 'doc').
- $container : ContainerInterface|null = null
-
Optional DI container instance used to resolve models.
- $init : array<string|int, mixed> = []
-
Optional associative array used for variable initialization in nested joins.
- $isArray : bool = false
-
If true, the join key is treated as an array of keys, generating an
INfilter.
Tags
Return values
string —The complete AQL 'LET' statement.
buildJoinVariables()
Generates a string of multiple AQL 'LET' statements for all defined joins variables.
buildJoinVariables([array<string|int, mixed> &$variables = [] ][, array<string|int, mixed> $definitions = [] ][, string $docRef = AQL::DOC ][, ContainerInterface|null $container = null ][, array<string|int, mixed> $init = [] ]) : string
Definition-level gating: a definition declaring AQL::REQUIRES that the
request-scoped authorizer denies is skipped — its LET is not emitted.
Parameters
- $variables : array<string|int, mixed> = []
- $definitions : array<string|int, mixed> = []
- $docRef : string = AQL::DOC
- $container : ContainerInterface|null = null
- $init : array<string|int, mixed> = []
Tags
Return values
stringbuildPolymorphicJoinVariable()
Builds a single AQL 'LET' subquery for a *polymorphic* join — a join whose target collection is chosen at query time from a discriminator field of the parent document.
buildPolymorphicJoinVariable(string|null $name[, array<string|int, mixed> $definition = [] ][, string $docRef = AQL::DOC ][, ContainerInterface|null $container = null ][, array<string|int, mixed> $init = [] ][, bool $isArray = false ]) : string
The whole branch machinery (guarding, per-branch permission gating, the
FALLBACK branch, the APPEND combine) lives in the shared
buildPolymorphicRelationVariable(); this function only resolves the
join-specific shared defaults — the parent key path (Arango::PROPERTY,
defaulting to $name) and the foreign key attribute (Arango::KEY) — and
supplies the per-branch builder that wraps buildJoinSubquery().
The resulting LET always holds an array — exactly like a regular join —
so the projection layer (aqlFieldObject())
unwraps it with FIRST() for a Filter::JOIN or keeps the whole array for a
Filter::JOINS.
Example output (single Filter::JOIN, two branches):
LET area = APPEND(
( FOR doc_join IN warehouses
FILTER doc_join._key == doc.selector.areaServed
&& doc.selector.areaScope == "…#Warehouse"
RETURN { _key: doc_join._key, name: doc_join.name } ) ,
( FOR doc_join IN subsidiaries
FILTER doc_join._key == doc.selector.areaServed
&& doc.selector.areaScope == "…#Company"
RETURN { _key: doc_join._key, name: doc_join.name } )
)
Parameters
- $name : string|null
-
The join field name — also the default
LETvariable name and the default parent key path. - $definition : array<string|int, mixed> = []
-
The polymorphic join definition. Keys:
Arango::DISCRIMINATOR(string) Parent field path deciding the branch (required).Arango::MAP(array) Non-emptytype => join-definitiontable (required).Arango::PROPERTY(string|null) Shared parent key path (default:$name).Arango::KEY(string|null) Shared foreign key attribute (default per branch:_key).Arango::UNIQUE(string|null) OptionalLETvariable name, overrides$name.Arango::FALLBACK(array|null) Join definition for unmatched discriminator values (null= none).
- $docRef : string = AQL::DOC
-
The AQL variable name of the main document reference.
- $container : ContainerInterface|null = null
-
Optional DI container used to resolve branch models.
- $init : array<string|int, mixed> = []
-
Optional associative array used for variable initialization.
- $isArray : bool = false
-
If true, each branch matches an array of keys (
IN).
Tags
Return values
string —The complete AQL 'LET' statement.
sortJoinVariable()
Generates the internal AQL 'SORT' clause for a join variable subquery.
sortJoinVariable(array<string|int, mixed>|string|null $definition[, string $docRef = AQL::DOC_JOIN ][, string $defaultProperty = Schema::_KEY ]) : string
This helper interprets a flexible sort definition and constructs the appropriate
AQL 'SORT' expression. Unlike an edge relation, a join has a single document
variable ($docRef), so both the explicit sort property and the default fallback
target that same reference.
- If $definition is an array: looks for
AQL::SORT(property) andAQL::ORDER(ASC/DESC) and sorts by that property on the join document. - If $definition is a string (legacy): sorts by that string as the property on the join document in ASC order.
- If $definition is null (or
AQL::SORTis not set in the array): sorts by the $defaultProperty (e.g. '_key') on the join document in DESC order.
Parameters
- $definition : array<string|int, mixed>|string|null
-
The sort configuration. Typically the
$definitionarray from buildJoinVariable. - $docRef : string = AQL::DOC_JOIN
-
The internal AQL join-document variable reference (default: 'doc_join').
- $defaultProperty : string = Schema::_KEY
-
The fallback property to sort by (default: '_key').
Tags
Return values
string —The generated AQL 'SORT' clause.