Oihana PHP Arango

facets

Table of Contents

Functions

resolveFacetDirection()  : string
Resolves the traversal direction of a linked facet: which way its edges are followed from the listed document.
resolveFacetJoin()  : array{0: string, 1: string, 2: string}
Resolves the **anchor** of a key-join facet: the `FOR` opening the joined collection and the predicate tying a joined document to the main one.
resolveFacetValue()  : array{0: mixed, 1: mixed, 2: mixed}|null
Reads a facet value coming from the URL, letting the `{op, val, alt}` request object override the operator and the `alt` chain declared in the facet definition.

Functions

resolveFacetDirection()

Resolves the traversal direction of a linked facet: which way its edges are followed from the listed document.

resolveFacetDirection(array<string|int, mixed> $facet) : string

The direction is not a detail of the AQL — it decides whether the facet finds anything at all. A model whose edges leave the document (doc is the _from) reaches its vertices OUTBOUND; one whose edges point at it reaches them INBOUND. Follow the wrong way and the traversal is perfectly valid and matches nothing, so the facet answers empty buckets in 200 without a word — the shape of silent degradation this library refuses.

Three rules, and each is deliberate:

  • the default is Traversal::INBOUND, which is what every linked facet compiled before this option existed — so a declaration that says nothing keeps its query byte for byte;
  • Traversal::ANY is accepted, and means what it says: linked in either direction. It is the right answer for a relation that is not oriented — with the caveat that a document linked both ways to the same vertex is then reached twice, so Facet::DISTINCT earns its keep;
  • an unknown value is refused, never quietly replaced. Traversal::get() would have fallen back on the default, turning a typo into empty buckets — the very failure the option exists to close — so Traversal::validate() answers instead.
Parameters
$facet : array<string|int, mixed>

The facet definition. Reads AQL::DIRECTION.

Tags
throws
ConstantException

When the declared direction is not a Traversal keyword.

example
use function oihana\arango\models\helpers\facets\resolveFacetDirection;

resolveFacetDirection( [] ) ;                                        // 'INBOUND'  (the default)
resolveFacetDirection( [ AQL::DIRECTION => Traversal::OUTBOUND ] ) ; // 'OUTBOUND'
resolveFacetDirection( [ AQL::DIRECTION => 'sideways' ] ) ;          // throws
since
1.7.0
author

Marc Alcaraz

Return values
string —

The validated direction keyword.

resolveFacetJoin()

Resolves the **anchor** of a key-join facet: the `FOR` opening the joined collection and the predicate tying a joined document to the main one.

resolveFacetJoin(string $key, array<string|int, mixed> $facet, string $doc) : array{0: string, 1: string, 2: string}

The three join facets — HasFacetJoin, HasFacetJoinAggregate and HasFacetJoinComplex — differ in what they do with the joined documents (test their existence, aggregate a numeric field over them, match several of their fields), never in how they reach them. That reaching is this helper: it reads the join definition and returns the three fragments every one of them needs.

The join is doc_<key>.<AQL::KEY> == doc.<Facet::PROPERTY>, with AQL::KEY the joined side (default _key) and Facet::PROPERTY the main side (default the facet key) — which expresses both "the document holds the foreign key" and the reverse one-to-many "the joined documents reference the document". When AQL::ARRAY is set the main side holds an array of keys, so the equality becomes a membership test (IN).

Parameters
$key : string

The facet key; drives the joined document reference (doc_<key>) and the default main-side property.

$facet : array<string|int, mixed>

The facet definition (AQL::COLLECTION, AQL::KEY, Facet::PROPERTY, AQL::ARRAY).

$doc : string

The main document reference.

Tags
throws
ReflectionException
example
use function oihana\arango\models\helpers\facets\resolveFacetJoin;

// Posts joined to their author: doc.authorId == author._key
[ $docRef , $for , $match ] = resolveFacetJoin( 'author' , [ AQL::COLLECTION => 'authors' , Facet::PROPERTY => 'authorId' ] , 'doc' ) ;
// $docRef = 'doc_author'
// $for    = 'FOR doc_author IN authors'
// $match  = 'doc_author._key == doc.authorId'

// The main document holds an array of keys
[ , , $match ] = resolveFacetJoin( 'tags' , [ AQL::COLLECTION => 'tags' , AQL::ARRAY => true , Facet::PROPERTY => 'tagIds' ] , 'doc' ) ;
// $match = 'doc_tags._key IN doc.tagIds'
since
1.6.0
author

Marc Alcaraz

Return values
array{0: string, 1: string, 2: string} —

A [ docRef , for , match ] triplet: the joined document reference, the FOR doc_<key> IN <collection> clause, and the join predicate to place in the FILTER.

resolveFacetValue()

Reads a facet value coming from the URL, letting the `{op, val, alt}` request object override the operator and the `alt` chain declared in the facet definition.

resolveFacetValue(mixed $value, mixed $op, mixed $alt) : array{0: mixed, 1: mixed, 2: mixed}|null

A facet accepts two shapes on the wire — the bare value (?facets={"author":"alice"}) and the object form (?facets={"author":{"op":"like","val":"al"}}). Only the object form may override the configuration, and only through the keys it actually carries: the caller passes its already-resolved defaults in, and gets back the triplet to keep working with.

An associative array is the object form; a list is a multi-value bare value (["alice","bob"]) and travels untouched.

The presence of val is tested with array_key_exists(), not isset(), so an explicit {"op":"eq","val":null} is honoured as a null value rather than read as a missing one. An object form with no val at all cannot be compared against anything: the helper returns null and the caller drops the facet — which is why the abandon signal is a null return, and not a null value.

Parameters
$value : mixed

The raw facet value from the request.

$op : mixed

The operator declared by the facet definition, used unless overridden.

$alt : mixed

The alt chain declared by the facet definition, used unless overridden.

Tags
example
use function oihana\arango\models\helpers\facets\resolveFacetValue;

resolveFacetValue( 'alice' , 'eq' , null ) ;                              // [ 'eq' , null , 'alice' ]
resolveFacetValue( [ 'op' => 'like' , 'val' => 'al' ] , 'eq' , null ) ;   // [ 'like' , null , 'al' ]
resolveFacetValue( [ 'op' => 'like' ] , 'eq' , null ) ;                   // null — nothing to compare
resolveFacetValue( [ 'alice' , 'bob' ] , 'eq' , null ) ;                  // [ 'eq' , null , ['alice','bob'] ]
since
1.6.0
author

Marc Alcaraz

Return values
array{0: mixed, 1: mixed, 2: mixed}|null —

The [ op , alt , value ] triplet to carry on with, or null when the request object carries no val and the facet has nothing to compare.

On this page

Search results