Oihana PHP Arango

FacetTrait uses trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short

This trait defines all facet helpers in the Model class.

Table of Contents

Constants

FACETS  : string = 'facets'
The 'facets' parameter constant.

Properties

$facets  : array<string|int, mixed>|null
The facet settings.

Methods

initializeFacets()  : static
Initialize the 'facets' property.
prepareFacetArrayComplex()  : string
Prepares an array complex facet.
prepareFacetEdge()  : string
Prepares a facet condition with an edge definition.
prepareFacetEdgeAggregate()  : string
Prepares an edge aggregate facet.
prepareFacetEdgeComplex()  : string
Prepares an edge complex facet.
prepareFacetField()  : string
Prepares a field facet (scalar property comparison, `=~` match by default).
prepareFacetIn()  : string
Prepares an array membership facet.
prepareFacetJoin()  : string
Prepares a simple join facet.
prepareFacetJoinAggregate()  : string
Prepares a join aggregate facet.
prepareFacetJoinComplex()  : string
Prepares a join complex facet.
prepareFacetList()  : string
Prepares a list facet (array membership, `ANY IN` by default).
prepareFacetListField()  : string
Prepares a list field facet (array membership, `ANY IN` by default).
prepareFacetListFieldSorted()  : string
Prepares a sortable list field facet: same membership as {@see prepareFacetListField()}, plus a `SORT POSITION(...)` clause that ranks the matched documents by the order of the requested values (a value appearing first in the request sorts first).
prepareFacets()  : string|null
Prepare the query with AQL facets definitions.
negatedComparator()  : string|null
Returns the negative counterpart of an operator code, or null when it has none (ordering operators, already-negative operators, …).
prepareFacetFieldBetween()  : string
Builds an inclusive `between` (range) field facet: `(LEFT >= @min && LEFT <= @max)`.

Constants

FACETS

The 'facets' parameter constant.

public string FACETS = 'facets'

Properties

$facets

The facet settings.

public array<string|int, mixed>|null $facets = []

Methods

initializeFacets()

Initialize the 'facets' property.

public initializeFacets([array<string|int, mixed> $init = [] ]) : static
Parameters
$init : array<string|int, mixed> = []
Return values
static

prepareFacetArrayComplex()

Prepares an array complex facet.

protected prepareFacetArrayComplex(string $key, mixed $value, array<string|int, mixed> &$binds[, array<string|int, mixed> $facet = [] ][, string $docRef = AQL::DOC ]) : string

Keeps documents whose embedded array property ($docRef.$key) holds at least one element matching the requested sub-field conditions, expressed as an existential traversal LENGTH(FOR e IN $docRef.$key FILTER ... ) > 0. The value is an object of subField: condition pairs; each condition may be a single value or a list, and any value may be negated with a leading - (!=). Negation is inline in the existential, so it keeps documents having an element that does NOT equal the value (not "exclude the value").

Parameters
$key : string

The facet key, also the embedded array property name.

$value : mixed

The sub-field conditions (object of value or list).

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed> = []

The facet definition (reads a facet-wide Facet::ALT, applied to every sub-field).

$docRef : string = AQL::DOC

The document reference the array is read from (default doc).

Tags
throws
BindException
ReflectionException
ValidationException
UnsupportedOperationException
example

Set the facetable definition in the model :

Arango::FACETS =>
[
    Prop::WORKSHOPS =>
    [
        Facet::TYPE => Facet::ARRAY_COMPLEX
    ]
]

Use the facet :

?facets={"workshops":{"breeding.alternateName":"pig"}}            // an element with breeding.alternateName == pig
?facets={"workshops":{"breeding.alternateName":["pig","cattle"]}} // an element == pig OR == cattle
?facets={"workshops":{"breeding.alternateName":["-pig","cattle"]}}// an element != pig AND != cattle
Return values
string

prepareFacetEdge()

Prepares a facet condition with an edge definition.

protected prepareFacetEdge(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string
Parameters
$key : string
$value : mixed
$binds : array<string|int, mixed>
$facet : array<string|int, mixed>
$doc : string
Tags
throws
BindException
ReflectionException
example

Set the facetable definition in the model :

Arango::FACETS =>
[
    Prop::LOCATION =>
    [
       Facet::TYPE => Facet::EDGE ,
       Facet::EDGE => 'organizations_places'
    ]
]

Exact match on _key (default operator eq, single field) :

?facets={"location":1234}          // linked to vertex 1234
?facets={"location":"1234,5678"}   // linked to 1234 OR 5678
?facets={"location":"-1234"}       // NOT linked to 1234        (LENGTH(...) == 0)
?facets={"location":"1234,-5678"}  // linked to 1234 AND not linked to 5678

Search several vertex fields with like (the former THESAURUS) :

Prop::SUBJECTS =>
[
    Facet::TYPE => Facet::EDGE ,
    Facet::EDGE => 'has_subject' ,
    AQL::FIELDS => '_key,name,alternateName' , // OR across these fields
    Facet::OP   => 'like'                      // CONTAINS-like with % wildcards
]
// ?facets={"subjects":"art"} => a linked subject whose _key, name OR alternateName LIKE @art

Values are comma-separated and OR-ed; a leading - negates a value, excluding the document. See HasFacetSimpleConditions for the full operator catalogue and multi-field behaviour.

Return values
string

prepareFacetEdgeAggregate()

Prepares an edge aggregate facet.

protected prepareFacetEdgeAggregate(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string
Parameters
$key : string

The facet key (also the related-document variable suffix).

$value : mixed

A scalar threshold, or an {agg, field, op, val} object.

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

The facet definition (AQL::EDGE, Facet::AGG, AQL::FIELDS, Facet::OP).

$doc : string

The main document reference.

Tags
throws
BindException
ReflectionException
ValidationException
example

Average revenue of all linked balance sheets — keep organisations above a threshold :

Arango::FACETS =>
[
    'balanceSheets' =>
    [
        Facet::TYPE => Facet::EDGE_AGGREGATE ,
        AQL::EDGE   => 'balance_edges' , // edge collection (INBOUND doc)
        Facet::AGG  => 'avg' ,           // default aggregator
        AQL::FIELDS => 'revenue' ,       // default aggregated field
        Facet::OP   => 'ge'              // default threshold comparator
    ]
]
?facets={"balanceSheets":{"agg":"avg","field":"revenue","op":"ge","val":1000000}}
// AVERAGE(FOR doc_balanceSheets IN INBOUND doc balance_edges RETURN doc_balanceSheets.revenue) >= @balanceSheets_0

?facets={"balanceSheets":{"agg":"count","op":"ge","val":3}}  // at least 3 linked balance sheets
?facets={"balanceSheets":{"agg":"sum","field":"revenue","val":5000000}}  // cumulative revenue >= 5M
?facets={"balanceSheets":5}  // defaults (count, ge): at least 5 linked balance sheets
Return values
string

prepareFacetEdgeComplex()

Prepares an edge complex facet.

protected prepareFacetEdgeComplex(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string

The value is an object of field: condition pairs, ALL matched on the SAME inbound vertex (AND). Each field condition may be a single value, a list of values (OR), and any value may be negated with a leading -. Because every condition applies to the same traversed vertex, negation stays inline (!=) inside the existential traversal — {value:"-459"} keeps documents linked to a vertex whose value != 459, which differs from the plain HasFacetEdge facet's "not linked to" semantics.

Parameters
$key : string
$value : mixed
$binds : array<string|int, mixed>
$facet : array<string|int, mixed>
$doc : string
Tags
throws
BindException
ReflectionException
UnsupportedOperationException
ValidationException
example

Set the facetable definition in the model :

Arango::FACETS =>
[
    Prop::NUMBERS =>
    [
        Facet::TYPE => Facet::EDGE_COMPLEX,
        Facet::EDGE => 'livestocks_has_numbers'
    ]
]

Use the facet :

?facets={"numbers":{"value":"459875642"}}            // value == 459875642
?facets={"numbers":{"value":"459","kind":"ear"}}     // value == 459 AND kind == ear (same vertex)
?facets={"numbers":{"value":["459","460"]}}          // value == 459 OR value == 460
?facets={"numbers":{"value":"-459","kind":"ear"}}    // value != 459 AND kind == ear (same vertex)
?facets={"numbers":{"value":["459","-460"]}}         // value == 459 AND value != 460
Return values
string

prepareFacetField()

Prepares a field facet (scalar property comparison, `=~` match by default).

protected prepareFacetField(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string

The operator defaults to match (regex =~, backward compatible). It can be set in the facet definition (Facet::OP) or overridden per request with an {op, val} object. Operator codes reuse FilterComparator.

Parameters
$key : string

The facet key (also the default document property).

$value : mixed

A CSV string, a list, or an {op, val} object selecting the operator per request.

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

The facet definition (Facet::PROPERTY, Facet::OP).

$doc : string

The document reference the property is read from.

Tags
throws
BindException
UnsupportedOperationException
ValidationException
example

Set the facetable definition in the model (operator optional, defaults to match; it can also be overridden per request) :

Arango::FACETS =>
[
    Prop::WITH_STATUS => [ Facet::TYPE => Facet::FIELD ] ,                                  // =~ (default)
    Prop::ID          => [ Facet::TYPE => Facet::FIELD , Facet::PROPERTY => '_key' , Facet::OP => FilterComparator::EQ ] , // ==
    Prop::PRICE       => [ Facet::TYPE => Facet::FIELD , Facet::OP => FilterComparator::GE ] // >=
]

Default operator — regex match, comma-separated values are OR-ed :

?facets={"withStatus":"under_review"}            // (doc.withStatus =~ @0)
?facets={"withStatus":"draft,under_review"}      // (doc.withStatus =~ @0 || doc.withStatus =~ @1)

Negation — a leading - switches to the negative operator and ANDs the group :

?facets={"withStatus":"-draft"}                  // (doc.withStatus !~ @0)
?facets={"withStatus":"-under_review,-draft"}    // (doc.withStatus !~ @0 && doc.withStatus !~ @1)

Pick the operator per request with {op, val} :

?facets={"withStatus":{"op":"eq","val":"draft"}} // (doc.withStatus == @0)   exact, not regex
?facets={"price":{"op":"ge","val":100}}          // (doc.price >= @0)
?facets={"name":{"op":"like","val":"jo%"}}       // (doc.name LIKE @0)
?facets={"withStatus":{"op":"eq","val":"-draft"}}// (doc.withStatus != @0)   negation, generic

Supported operators: eq, ne, gt, ge, lt, le, like, nlike, match (default), nmatch. An unknown op falls back to match.

Return values
string

prepareFacetIn()

Prepares an array membership facet.

protected prepareFacetIn(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc[, bool $sortable = false ]) : string
Parameters
$key : string

The facet key (also the default document array property).

$value : mixed

Either a CSV string ("a,b"), a list (["a","b"]) or an {op, val} object selecting the operator per request.

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

The facet definition (Facet::PROPERTY, Facet::OP).

$doc : string

The document reference the array is read from.

$sortable : bool = false

When true, append SORT POSITION(...) to order by the requested values.

Tags
throws
BindException
UnsupportedOperationException
ValidationException
example

Set the facetable definition in the model (operator optional, defaults to any.in; it can also be overridden per request) :

Arango::FACETS =>
[
    Prop::KEYWORDS =>
    [
        Facet::TYPE     => Facet::IN ,
        Facet::PROPERTY => Prop::KEYWORDS ,
        Facet::OP       => FilterArrayComparator::ANY_IN // optional default
    ]
]

Value forms — a CSV string, a list, or an {op, val} object :

?facets={"keywords":"cuisine,jardin"}                        // ANY IN  : has cuisine OR jardin
?facets={"keywords":["cuisine","jardin"]}                    // ANY IN  : array form, same result
?facets={"keywords":{"op":"all.in","val":"cuisine,jardin"}}  // ALL IN  : has BOTH values
?facets={"keywords":{"op":"none.in","val":["cuisine"]}}      // NONE IN : has NEITHER value
?facets={"keywords":{"op":"any.nin","val":"cuisine,jardin"}} // ANY NOT IN

Operator codes reuse the filter vocabulary (FilterArrayComparator): any.in (default), all.in, none.in, any.nin, all.nin, none.nin, …

Property aliasing — the URL facet key is decoupled from the document property via Facet::PROPERTY (e.g. expose id but target _key):

Arango::FACETS => [ 'id' => [ Facet::TYPE => Facet::IN , Facet::PROPERTY => '_key' ] ]
?facets={"id":"k1,k2"}   // => TO_ARRAY([@id_0,@id_1]) ANY IN doc._key

Generated AQL (default any.in) :

TO_ARRAY([@keywords_0,@keywords_1]) ANY IN doc.keywords

With $sortable = true (the Facet::LIST_FIELD_SORTED entry point), a SORT POSITION(...) clause is appended to rank by the requested order :

TO_ARRAY([@keywords_0,@keywords_1]) ANY IN doc.keywords SORT POSITION([@keywords_0,@keywords_1],doc.keywords,true)
Return values
string

prepareFacetJoin()

Prepares a simple join facet.

protected prepareFacetJoin(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string
Parameters
$key : string

The facet key (also the default main-side join property).

$value : mixed

A scalar, CSV string, list, or {op, val} object matched against the joined field(s).

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

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

$doc : string

The main document reference.

Tags
throws
BindException
example

Filter posts by their author's name (join authors on post.authorId == author._key) :

Arango::FACETS =>
[
    Prop::AUTHOR =>
    [
        Facet::TYPE     => Facet::JOIN ,
        AQL::COLLECTION => 'authors' ,
        Facet::PROPERTY => 'authorId' , // main side  (default the facet key)
        AQL::KEY        => '_key' ,      // joined side (default _key)
        AQL::FIELDS     => 'name'        // searched field(s), default _key
    ]
]
?facets={"author":"alice"}        // a joined author whose name == alice
?facets={"author":"alice,bob"}    // name == alice OR bob
?facets={"author":"-spammer"}     // exclude posts joined to author "spammer"
?facets={"author":{"op":"like","val":"al"}}  // name LIKE @al
Return values
string

prepareFacetJoinAggregate()

Prepares a join aggregate facet.

protected prepareFacetJoinAggregate(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string
Parameters
$key : string

The facet key (also the default main-side join property).

$value : mixed

A scalar threshold, or an {agg, field, op, val} object.

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

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

$doc : string

The main document reference.

Tags
throws
BindException
ValidationException
example

Average comment score per article — keep articles rated 4 or more on average :

Arango::FACETS =>
[
    'comments' =>
    [
        Facet::TYPE     => Facet::JOIN_AGGREGATE ,
        AQL::COLLECTION => 'comments' ,  // joined collection
        AQL::KEY        => 'articleId' , // joined side  (default _key)
        Facet::PROPERTY => '_key' ,      // main side    (default the facet key)
        Facet::AGG      => 'avg' ,       // default aggregator
        AQL::FIELDS     => 'score' ,     // default aggregated field
        Facet::OP       => 'ge'          // default threshold comparator
    ]
]
?facets={"comments":{"agg":"avg","field":"score","op":"ge","val":4}}
// AVERAGE(FOR doc_comments IN comments FILTER doc_comments.articleId == doc._key RETURN doc_comments.score) >= @comments_0

?facets={"comments":{"agg":"count","val":3}}      // at least 3 comments
?facets={"comments":{"agg":"min","field":"score","val":3}}  // worst score still >= 3
?facets={"comments":{"agg":"count","op":"lt","val":2}}      // lightly commented (fewer than 2)
Return values
string

prepareFacetJoinComplex()

Prepares a join complex facet.

protected prepareFacetJoinComplex(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string
Parameters
$key : string

The facet key (also the default main-side join property).

$value : mixed

The object of field: condition pairs tested on the joined document.

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

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

$doc : string

The main document reference.

Tags
throws
BindException
ReflectionException
UnsupportedOperationException
ValidationException
example

Reverse one-to-many — the joined documents reference the main one :

Arango::FACETS =>
[
    Prop::COMMENTS =>
    [
        Facet::TYPE     => Facet::JOIN_COMPLEX ,
        AQL::COLLECTION => 'comments' ,
        AQL::KEY        => 'articleId' ,  // joined side (default _key)
        Facet::PROPERTY => '_key'         // main side  (default the facet key)
    ]
]

One-to-one — the main document holds the foreign key (defaults: KEY=_key, PROPERTY=facet key) :

Prop::PLACE => [ Facet::TYPE => Facet::JOIN_COMPLEX , AQL::COLLECTION => 'places' ]

One-to-many by array — the main document holds an array of keys :

Prop::TAGS => [ Facet::TYPE => Facet::JOIN_COMPLEX , AQL::COLLECTION => 'tags' , AQL::ARRAY => true , Facet::PROPERTY => 'tagIds' ]

Use the facet (sub-fields behave exactly like EDGE_COMPLEX) :

?facets={"comments":{"status":"approved"}}                 // a comment with status == approved
?facets={"comments":{"status":"approved","score":"5"}}     // status == approved AND score == 5
?facets={"comments":{"status":["approved","featured"]}}    // status == approved OR featured
?facets={"comments":{"status":"-spam"}}                    // a comment whose status != spam
Return values
string

prepareFacetList()

Prepares a list facet (array membership, `ANY IN` by default).

protected prepareFacetList(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string

Accepts a CSV string, a list, or an {op, val} object selecting the operator per request (FilterArrayComparator).

Parameters
$key : string
$value : mixed
$binds : array<string|int, mixed>
$facet : array<string|int, mixed>
$doc : string
Tags
throws
BindException
example

Set the facetable definition in the model :

Arango::FACETS =>
[
    Prop::KEYWORDS =>
    [
        Facet::TYPE     => Facet::LIST ,
        Facet::PROPERTY => Prop::KEYWORDS
    ]
]

Use the facet (array membership tested against doc.keywords) :

?facets={"keywords":"key1,key2"}                        // ANY IN  : has key1 OR key2
?facets={"keywords":["key1","key2"]}                    // ANY IN  : array form, same result
?facets={"keywords":{"op":"all.in","val":"key1,key2"}}  // ALL IN  : has BOTH
?facets={"keywords":{"op":"none.in","val":["key1"]}}    // NONE IN : has NEITHER

Generated AQL (default any.in) :

TO_ARRAY([@keywords_0,@keywords_1]) ANY IN doc.keywords
Return values
string

prepareFacetListField()

Prepares a list field facet (array membership, `ANY IN` by default).

protected prepareFacetListField(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc[, bool $sortable = false ]) : string

Historical alias of HasFacetIn::prepareFacetIn() — see that method for the full operator catalogue (any.in, all.in, none.in, …).

Parameters
$key : string
$value : mixed
$binds : array<string|int, mixed>
$facet : array<string|int, mixed>
$doc : string
$sortable : bool = false
Tags
throws
BindException
example

Set the facetable definition in the model :

Arango::FACETS =>
[
    Prop::KEYWORDS =>
    [
        Facet::TYPE     => Facet::LIST_FIELD ,
        Facet::PROPERTY => Prop::KEYWORDS
    ]
]

Use the facet (array membership tested against doc.keywords) :

?facets={"keywords":"cuisine,jardin"}                        // ANY IN  : has cuisine OR jardin
?facets={"keywords":["cuisine","jardin"]}                    // ANY IN  : array form, same result
?facets={"keywords":{"op":"all.in","val":"cuisine,jardin"}}  // ALL IN  : has BOTH
?facets={"keywords":{"op":"none.in","val":"cuisine"}}        // NONE IN : has NEITHER

Generated AQL (default any.in) :

TO_ARRAY([@keywords_0,@keywords_1]) ANY IN doc.keywords
Return values
string

prepareFacetListFieldSorted()

Prepares a sortable list field facet: same membership as {@see prepareFacetListField()}, plus a `SORT POSITION(...)` clause that ranks the matched documents by the order of the requested values (a value appearing first in the request sorts first).

protected prepareFacetListFieldSorted(string $key, mixed $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc) : string
Parameters
$key : string
$value : mixed
$binds : array<string|int, mixed>
$facet : array<string|int, mixed>
$doc : string
Tags
throws
BindException
example

Set the facetable definition in the model :

Arango::FACETS =>
[
    Prop::TAGS =>
    [
        Facet::TYPE     => Facet::LIST_FIELD_SORTED ,
        Facet::PROPERTY => Prop::TAGS
    ]
]

Use the facet — keep articles tagged featured, new or sale, ranked in that priority order :

?facets={"tags":"featured,new,sale"}
?facets={"tags":["featured","new","sale"]}

Generated AQL :

TO_ARRAY([@tags_0,@tags_1,@tags_2]) ANY IN doc.tags SORT POSITION([@tags_0,@tags_1,@tags_2],doc.tags,true)
Return values
string

prepareFacets()

Prepare the query with AQL facets definitions.

protected prepareFacets(array<string|int, mixed>|null $init[, array<string|int, mixed>|null &$binds = null ][, string $docRef = AQL::DOC ][, string $logicalOperator = Logic::AND ]) : string|null
Parameters
$init : array<string|int, mixed>|null
$binds : array<string|int, mixed>|null = null
$docRef : string = AQL::DOC
$logicalOperator : string = Logic::AND
Return values
string|null

negatedComparator()

Returns the negative counterpart of an operator code, or null when it has none (ordering operators, already-negative operators, …).

private negatedComparator(string $op) : string|null
Parameters
$op : string
Return values
string|null

prepareFacetFieldBetween()

Builds an inclusive `between` (range) field facet: `(LEFT >= @min && LEFT <= @max)`.

private prepareFacetFieldBetween(string $key, array<string|int, mixed> $value, array<string|int, mixed> &$binds, array<string|int, mixed> $facet, string $doc, mixed $alt) : string

The compared property is alt-aware (the key-side chain wraps doc.<property>). An omitted bound drops its side (one-sided range), mirroring the number/string ?filter= semantics; both omitted yields an empty fragment.

Parameters
$key : string

The facet key.

$value : array<string|int, mixed>

The request object (min, max).

$binds : array<string|int, mixed>

The bind variables, populated by reference.

$facet : array<string|int, mixed>

The facet definition (Facet::PROPERTY).

$doc : string

The document reference.

$alt : mixed

The resolved alt parameter (request over definition).

Tags
throws
BindException
UnsupportedOperationException
ValidationException
Return values
string
On this page

Search results