Reference filtering is used to filter entities based on their references to other entities in the catalog or
attributes specified in those relations.
Reference having
argument:string!
the name of the entity reference that will be subjected to the filtering
constraints in the second and subsequent arguments
filterConstraint:any+
one or more filter constraints that must be satisfied by one of the entity references with name specified in
the first argument
The
constraint
eliminates entities which has no reference of particular name satisfying set of filtering constraints. You can examine
either the attributes specified on the relation itself, wrap the filtering constraint
in entityHaving constraint to examine the attributes of the referenced entity,
or in groupHaving constraint to examine the attributes of the group entity associated
with the reference. The constraint is similar to
SQL EXISTS operator.
How the nested constraints are evaluated
Every constraint nested inside referenceHaving describes a single reference. An entity matches when at
least one of its references with the given name satisfies all of those constraints at once. This is what the
similarity to the SQL EXISTS operator means in practice: the query asks whether such a reference exists, not
whether the entity as a whole has a particular property.
The distinction becomes visible as soon as an entity carries more than one reference of the same name.
Consider a product with two relatedProducts references - one whose category is alternativeProduct, and
another whose category is sparePart:
a constraint requiring category to equal alternativeProduct matches this product, because its first
reference satisfies it,
a constraint requiring categorynot to equal alternativeProduct matches it as well, because its
second reference satisfies that.
Both answers are correct. The two queries ask about different references of the same product, so there is
nothing contradictory about a product matching both of them.
The same rule governs constraints combined with and - all of them must be satisfied by one and the same
reference. A product whose first reference satisfies one condition while a different reference satisfies the
other does not match their conjunction. Likewise, entityHaving and
groupHaving describe the referenced entity and the group of that same single reference.
Negating inside the constraint differs from negating around it. Because every nested constraint describes
one reference, a negation placed inside referenceHaving asks whether some reference fails the condition.
To ask whether no reference satisfies it, negate the entire referenceHaving constraint instead.
referenceHaving("relatedProducts", not(attributeEquals("category", "alternativeProduct"))) matches entities
that have at least one related product which is not an alternative product.
not(referenceHaving("relatedProducts", attributeEquals("category", "alternativeProduct"))) matches entities
that have no related product which is an alternative product.
An entity may match both of these queries, or neither of them.
To demonstrate how the referenceHaving constraint works, let's query for products that have at least one alternative
product specified. The alternative products are stored in the relatedProducts reference on the Product entity and
have the category attribute set to alternativeProduct. There can be different types of related products other than
alternative products, for example spare parts and so on - that's why we need to specify the category attribute in
the filtering constraint.
Returns the following result:
If we wanted to query for products that have at least one related product reference of any category type, we could use
the following simplified query:
Which returns the following result:
Another frequently used use-case is to query for entities that have at least one reference to another entity with
certain primary key. For example, we want to query for products that are related to brand with primary key 66465.
This can be achieved by following query:
Which returns the following result:
Entity having
filterConstraint:any+
one or more filter constraints that must be satisfied by the target referenced entity of any of the source
entity references identified by the parent referenceHaving constraint
The entityHaving constraint is used to examine the attributes or other filterable properties of the referenced entity.
It can only be used within the referenceHaving constraint, which defines the name of the entity
reference that identifies the target entity to be subjected to the filtering restrictions in the entityHaving
constraint. The filtering constraints for the entity can use entire range
of filtering operators.
Let's use our previous example to query for products that relate to brand with particular attribute code:
Which returns the following result:
Group having
filterConstraint:any+
one or more filter constraints that must be satisfied by the group entity of any of the source
entity references identified by the parent referenceHaving constraint
The
constraint
is used to examine the attributes or other filterable properties of the group entity associated with a reference.
It can only be used within the referenceHaving constraint, which defines the name of the entity
reference whose group entity is subjected to the filtering restrictions in the groupHaving constraint. The filtering
constraints for the group entity can use the entire range of filtering operators.
This constraint requires the reference to be configured with a group type and to have the REFERENCED_GROUP_ENTITYindexed component enabled. The three sibling constraints address different
"layers" of a single reference and can be combined freely inside referenceHaving:
In the demo dataset, the parameterValues reference points to a ParameterValue entity (e.g. RAM 16 GB) and is
grouped by a Parameter entity (e.g. RAM memory). To find MacBooks that expose the RAM memory parameter at
all — regardless of how much memory each one has — you select the reference by its group, not by the individual
parameter values:
Note how groupHaving filters at the group level while the sibling referenceContentWithAttributes filter at the
fetch level uses entityHaving to project the matching individual values back into the result. This pairing —
"select by group, project by entity" — is the typical shape of a groupHaving query: the example narrows the
result to MacBooks that have at least one parameterValues reference whose group entity is the ram-memory
parameter, and then for each surviving MacBook fetches only those parameter values whose own code begins with
ram-memory (so the response shows the actual memory size without listing every other parameter the product exposes).
Facet having
argument:string!
the name of the entity reference that will be subject to the filtering
constraints in the second and subsequent arguments
filterConstraint:any*
zero or more filter constraints that identify the facet (reference) that must be present on the entities in
the result set
The
filtering
constraint is typically placed inside the userFilter constraint container and represents
the user's request to drill down the result set by a particular facet. The facetHaving constraint selects facets —
the referenced entities — and returns the entities referencing them, combined by the relations of the facet groups:
by default the selected facets of one group are combined by logical OR and the groups by logical AND, and a negated
group excludes the entities referencing its selected facets (see the
default reference calculation rules). It works in
conjunction with the referenceSummary requirement to correctly
calculate the facet statistics and impact predictions.
The nested constraints of facetHaving decide which facets are selected, not which references match. This is where
facetHaving differs from referenceHaving, whose nested constraints are
evaluated against each single reference.
A constraint on a reference attribute is evaluated over all references pointing to the facet together, pooled across
the entities that hold them. attributeEquals selects a facet when at least one reference to it carries the value,
and attributeIsNull selects a facet when none of the references to it carries the attribute (for a reference that
allows duplicates, the references sharing the same representative attribute values are pooled instead). An entity is
matched through a selected facet whether or not its own reference satisfies the constraint.
Reading the constraints per facet keeps the result consistent with the facet statistics, which are counted per facet.
Use referenceHaving when the constraint has to hold for the entity's own reference.
To demonstrate the cooperation between the facetHaving constraint inside userFilter and the referenceSummary
requirement, let's query for products in category e-readers and request the facet summary for reference brand.
At the same time, let's pretend that the user has already checked the amazon facet:
As you can see, when the facetHaving constraint is detected in the query and the corresponding facet statistics result
is marked as requested, our visualizer chooses to display the facet as checked. The other facet option statistics
reflect the fact that the user has already checked the amazon facet option and the predicted numbers are changed
accordingly:
Facet summary without facet requested
Facet summary after facet requested
Before
After
Because the facet summary JSON is quite long and not very readable, we will only show a simplified version of the facet
summary result in this documentation. As you can see, the selected facet is checked and the predicted numbers have
changed accordingly:
Including children
The
filtering constraint can only be placed within a facetHaving parent constraint and only if the parent constraint refers
to the hierarchical entity. This constraint will automatically propagate all child entities of any entity that matches
the facetHaving constraint to that parent constraint, as if the facetHaving contained the children directly.
Let's illustrate this situation with some real data. Imagine you have a category Laptops with subcategories Netbooks,
Ultrabooks and so on:
Laptops category listing
Products can be related to any of these sub-categories, or directly to the Laptops category (if they don't match any
of the sub-categories). If you generated a facet summary for the category reference, you'd get all the categories with
matching products on the same level. But you may want to visualise the category part of the facet summary as a tree
using the `hierarchy requirement. When the user selects one of
the category options, it should automatically select all subcategories as well, and also change the predicted
reference statistics accordingly.
To achieve this, you can use the includingChildren constraint within the facetHaving constraint. The query is also
restricted to the products of the ASUS manufacturer so that the facet summary is not too long:
Facet summary without including children requested
Facet summary after facet including children requested
Before
After
Because the facet summary JSON is quite long and not very readable, we will only show a simplified version of the facet
summary result in this documentation. As you can see, not only the facet laptops matched by equals function is checked,
but also all of its children. The predicted numbers have changed accordingly:
Including children having
filterConstraint:any+
one or more filter constraints that further narrow down the child entities that will be included in
the facetHaving parent constraint
The
filtering constraint is a specialisation of includingChildren that allows you to restrict
the child entities that are included in the facetHaving parent constraint. This can be useful if you are using
filters in the referenceSummary and your selection
logic needs to match it.
To better understand how the includingChildrenHaving constraint works, let's look at an example (the query is also
restricted to the products of the ASUS manufacturer so that the facet summary is not too long):
Facet summary with standard including children requested
Facet summary with limited facet including children having requested
Before
After
Because the facet summary JSON is quite long and not very readable, we will only show a simplified version of the facet
summary result in this documentation. As you can see, not only the laptops facet matched by the equals function is
checked, but also all of its children whose code attribute contains the string books. The predicted numbers have
changed accordingly:
Including children except
filterConstraint:any+
one or more filter constraints that excludes specific child entities from being included in
the facetHaving parent constraint
The
filtering constraint is a specialisation of includingChildren and exact opposite to [includingChildrenHaving]
that allows you to exclude the matched child entities from being included in the facetHaving parent constraint.
This can be useful if you are using filters in the
referenceSummary and your selection logic needs to
match it.
You can also combine the includingChildrenExcept constraint with the includingChildrenHaving constraint.
In this case, the includingChildrenHaving constraint is evaluated first and the includingChildrenExcept constraint
is applied to the result of the includingChildrenHaving constraint.
To better understand how the includingChildrenExcept constraint works, let's look at an example (the query is also
restricted to the products of the ASUS manufacturer so that the facet summary is not too long):
Facet summary with standard including children requested
Facet summary with limited facet including children except requested
Before
After
Because the facet summary JSON is quite long and not very readable, we will only show a simplified version of the facet
summary result in this documentation. As you can see, not only the laptops facet matched by the equals function is
checked, but also all of its children whose code attribute doesn't contain the string books. The predicted numbers
have changed accordingly:
Histogram having
argument:string!
the name of the entity reference that hosts the histogram to be narrowed
argument:string?
optional histogram name within the reference; may be omitted (or passed as null / empty string) when
the reference hosts exactly one histogram
argument:any?
optional inclusive lower bound (from) of the range; null leaves the range open-ended on the lower side
argument:any?
optional inclusive upper bound (to) of the range; null leaves the range open-ended on the upper side;
at least one of from / to must be non-null
filterConstraint:groupHaving?
optional single groupHaving constraint selecting the group entity for a grouped
histogram slot (for example "the height parameter" within the parameterValues reference); omitted for
non-grouped slots
Group primary key 0 is reserved. Reference histograms use the value 0 as a reserved non-grouped sentinel
across the entire subsystem (in histogramHaving range maps, in the grouped-vs-non-grouped slot key, and in the
ResolvedHistogramHaving carrier). Because evitaDB accepts client-supplied primary keys of any int value
(including negatives), you must not use 0 as a primary key for any entity that may appear as the group
of a reference hosting a histogram. A real group entity with PK 0 will be rejected with an internal error at
query time. Use any non-zero integer (positive or negative) for such entities.
The
constraint narrows a reference histogram to a specific [from, to] range. It is the first-class carrier for
slider-driven range selection on references — for example, a product's parameterValues reference that hosts one
histogram per parameter (height, weight, depth, …). A single histogramHaving identifies one
(referenceName, histogramName, groupSelector, [from, to]) tuple.
Inside the userFilter container, histogramHaving plays a dual role:
it is applied to the filter formula like any other userFilter child — the result set is narrowed by the range;
it is registered as a range carrier so the histogram's own [min, max] baseline cloner peels it out when
computing the histogram — moving one slider does not contract the [min, max] span of sibling sliders (see the
peel-by-family rule in behavioral filtering).
Outside userFilter, histogramHaving behaves like an equivalent referenceHaving rewrite —
it narrows the result set and does not participate in histogram baseline relaxation.
Expressing independent ranges on the same reference
Two histogramHaving siblings inside one userFilter express independent per-histogram ranges that are combined as
a logical AND — each slider has its own (histogramName, groupSelector, from, to) tuple. The example below narrows
the e-readers category to the products that simultaneously fall into the 200–400 g weight slice and the
6–10 mm thickness slice. Both sliders point at the same parameterValues reference and the same physical
histogram index (intervalParameterValues); the group selector — an groupHaving against the parameter group
entity — is what tells evitaDB which slot (weight vs thickness) each histogramHaving is talking about. The
sibling referenceSummaryOfReferenceWithHistograms in require() then asks the server to compute one full
histogram per parameter group, and because histogramHaving is registered as a range carrier inside userFilter,
each slider's own [min, max] span stays at the catalog-wide baseline rather than collapsing to the user's current
range: