evitaDB - Fast e-commerce database
logo
page-background

Hierarchy filtering

Hierarchy filtering allows you to query tree-oriented structures or items that refer to a node in that structure. In e-commerce projects, the hierarchy structure is represented by a category tree and the items that refer to it are usually products or some kind of "inventory". This functionality is closely related to menu traversal and listing the items relevant to the currently viewed category.

Hierarchy filtering can be applied only to entities marked as hierarchical or to entities that reference these hierarchical entities. Hierarchy filtering allows filtering all direct or transitive children of a given hierarchy node, or entities that are directly or transitively related to the requested hierarchy node or its children. Filtering allows to exclude (hide) several parts of the tree from evaluation, which can be useful in situation when part of the store should be (temporarily) hidden from (some of) clients.
In addition to filtering, there are query requirement extensions that allow you to compute data to help render (dynamic or static) menus that describe the hierarchy context you request in the query.
The typical use-cases related to hierarchy constraints:
There could be at most one single hierarchyWithin or hierarchyRoot filter constraint in the entire query.

Hierarchy within

The constraint
allows you to restrict the search to only those entities that are part of the hierarchy tree starting with the root node identified by the first argument of this constraint. In e-commerce systems the typical representative of a hierarchical entity is a category, which will be used in all of our examples. The examples in this chapter will focus on the category Accessories in our demo dataset with following layout:
Accessories category listingAccessories category listing

Self

filterConstraint:any!
a single mandatory filter constraint that identifies one or more hierarchy nodes that act as hierarchy roots; multiple constraints must be enclosed in AND / OR containers
filterConstraint:(directRelation|having|excluding|excludingRoot)*

optional constraints allow you to narrow the scope of the hierarchy; none or all of the constraints may be present:

The most straightforward usage is filtering the hierarchical entities themselves.

To list all nested categories of Accessories category issue this query:

... and you should get slightly more than one page of categories in the response.

The first argument specifies the filter targets the attributes of the Category entity. In this example we used attributeEquals for unique attribute code, but you can select the category by localized url attribute (but then you need to provide also entityLocaleEquals constraint for determining the proper language), or using entityPrimaryKeyInSet and passing category primary key.

Yes, it can. Although, it's apparently one of the edge cases, it's possible. This query:

... will return all subcategories of the Wireless headphones and Wired headphones and their subcategories:
Accessories category listingAccessories category listing

Referenced entity

argument:string!
a mandatory name of the queried entity reference schema that represents the relationship to the hierarchical entity type, your entity may target different hierarchical entities in different reference types, or it may target the same hierarchical entity through multiple semantically different references, and that is why the reference name is used instead of the target entity type.
filterConstraint:any!
a single mandatory filter constraint that identifies one or more hierarchy nodes that act as hierarchy roots; multiple constraints must be enclosed in AND / OR containers
filterConstraint:(directRelation|having|excluding|excludingRoot)*

optional constraints allow you to narrow the scope of the hierarchy; none or all of the constraints may be present:

The hierarchyWithin constraint can also be used for entities that directly reference a hierarchical entity type. The most common use case from the e-commerce world is a product that is assigned to one or more categories. To list all products in the Accessories category of our demo dataset, we issue the following query:
Products assigned to two or more subcategories of Accessories category will only appear once in the response (contrary to what you might expect if you have experience with SQL).

The query returns the first page of a total of 26 pages of items.

The category filter constraint specifies a condition that targets the referenced entity (i.e., category attributes, category references). Currently, it's not possible to specify a filter constraint that takes into account the product reference that leads to its category. An issue #105 is planned to address this shortcoming.

Hierarchy within root

The constraint
allows you to restrict the search to only those entities that are part of the entire hierarchy tree. In e-commerce systems the typical representative of a hierarchical entity is a category, which will be used in all of our examples.
The single difference to hierarchyWithin constraint is that it doesn't accept a root node specification. Because evitaDB accepts multiple root nodes in your entity hierarchy, it may be helpful to imagine there is an invisible "virtual" top root above all the top nodes (whose parent property remains NULL) you have in your entity hierarchy and this virtual top root is targeted by this constraint.
Root categories listingRoot categories listing

Self

filterConstraint:(directRelation|having|excluding)*

optional constraints allow you to narrow the scope of the hierarchy; none or all of the constraints may be present:

The hierarchyWithinRoot, which targets the Category collection itself, returns all categories except those that would point to non-existent parent nodes, such hierarchy nodes are called orphans and do not satisfy any hierarchy query.

The query returns the first page of a total of 2 pages of items.

Referenced entity

argument:string!
a mandatory name of the queried entity reference schema that represents the relationship to the hierarchical entity type, your entity may target different hierarchical entities in different reference types, or it may target the same hierarchical entity through multiple semantically different references, and that is why the reference name is used instead of the target entity type.
filterConstraint:(having|excluding)*

optional constraints allow you to narrow the scope of the hierarchy; none or all of the constraints may be present:

The hierarchyWithinRoot constraint can also be used for entities that directly reference a hierarchical entity type. The most common use case from the e-commerce world is a product that is assigned to one or more categories. To list all products assigned to any category of our demo dataset, we issue the following query:
Products assigned to only one orphan category will be missing from the result. Products assigned to two or more categories will only appear once in the response (contrary to what you might expect if you have experience with SQL).

The query returns the first page of a total of 212 pages of items:

Direct relation

The constraint
is a constraint that can only be used within hierarchyWithin or hierarchyWithinRoot parent constraints. It simply makes no sense anywhere else because it changes the default behavior of those constraints. Hierarchy constraints return all hierarchy children of the parent node or entities that are transitively or directly related to them and the parent node itself. If the directRelation is used as a sub-constraint, this behavior changes and only direct descendants or directly referencing entities are matched.

Self

If the hierarchy constraint targets the hierarchy entity, the directRelation will cause only the children of a direct parent node to be returned. In the case of the hierarchyWithinRoot constraint, the parent is an invisible "virtual" top root - so only the top-level categories are returned.
In the case of the hierarchyWithin the result will contain direct children of the filtered category (or categories).

Referenced entity

If the hierarchy constraint targets a non-hierarchical entity that references the hierarchical one (typical example is a product assigned to a category), it can only be used in the hierarchyWithin parent constraint.
In the case of hierarchyWithinRoot, the directRelation constraint makes no sense because no entity can be assigned to a "virtual" top parent root.
So we can only list products that are directly related to a certain category - if we try to list products that have Accessories category assigned:
... we get an empty result. There are no products directly assigned to the Accessories category, they all refer to some of its subcategories. Let's try the Smartwatches subcategory:
... and we get the list of all products related directly to a Smartwatches category.

Excluding root

The constraint
is a constraint that can only be used within hierarchyWithin or hierarchyWithinRoot parent constraints. It simply makes no sense anywhere else because it changes the default behavior of those constraints. Hierarchy constraints return all hierarchy children of the parent node or entities that are transitively or directly related to them and the parent node itself. When the excludingRoot is used as a sub-constraint, this behavior changes and the parent node itself or the entities directly related to that parent node are be excluded from the result.

Self

If the hierarchy constraint targets the hierarchy entity, the excludingRoot will omit the requested parent node from the result. In the case of the hierarchyWithinRoot constraint, the parent is an invisible "virtual" top root, and this constraint makes no sense.
As we can see the requested parent category Accessories is excluded from the result.

Referenced entity

If the hierarchy constraint targets a non-hierarchical entity that references the hierarchical one (typical example is a product assigned to a category), the excludingRoot constraint can only be used in the hierarchyWithin parent constraint.
In the case of hierarchyWithinRoot, the excludingRoot constraint makes no sense because no entity can be assigned to a "virtual" top parent root.
Because we learned that Accessories category has no directly assigned products, the excludingRoot constraint presence would not affect the query result. Therefore, we choose Keyboard category for our example. When we list all products in Keyboard category using hierarchyWithin constraint, we obtain 20 items. When the excludingRoot constraint is used:
... we get only 4 items, which means that 16 were assigned directly to Keyboards category and only 4 of them were assigned to Exotic keyboards:

Having

The constraint
is a constraint that can only be used within hierarchyWithin or hierarchyWithinRoot parent constraints. It simply makes no sense anywhere else because it changes the default behavior of those constraints. Hierarchy constraints return all hierarchy children of the parent node or entities that are transitively or directly related to them, and the parent node itself.
The having constraint allows you to set a constraint that must be fulfilled by all categories in the category scope in order to be accepted by hierarchy within filter. This constraint is especially useful if you want to conditionally display certain parts of the tree. Imagine you have a category Christmas Sale that should only be available during a certain period of the year, or a category B2B Partners that should only be accessible to a certain role of users. All of these scenarios can take advantage of the having constraint (but there are other approaches to solving the above use cases).
The lookup stops at the first node that doesn't satisfy the constraint!
The hierarchical query traverses from the root nodes to the leaf nodes. For each of the nodes, the engine checks whether the having constraint is still valid, and if not, it excludes that hierarchy node and all of its child nodes (entire subtree).
filterConstraint:+

one or more mandatory constraints that must be satisfied by all returned hierarchy nodes and that mark the visible part of the tree, the implicit relation between constraints is logical conjunction (boolean AND)

Self

When the hierarchy constraint targets the hierarchy entity, the children that don't satisfy the inner constraints (and their children, whether they satisfy them or not) are excluded from the result.

For demonstration purposes, let's list all categories within the Accessories category, but only those that are valid at 01:00 AM on October 1, 2023.
Accessories category listing with validity constraintAccessories category listing with validity constraint
Because the category Christmas electronics has its validity set to be valid only between December 1st and December 24th, it will be omitted from the result. If it had subcategories, they would also be omitted (even if they had no validity restrictions).

Referenced entity

If the hierarchy constraint targets a non-hierarchical entity that references the hierarchical one (typical example is a product assigned to a category), the having constraint is evaluated against the hierarchical entity (category), but affects the queried non-hierarchical entities (products). It excludes all products referencing categories that don't satisfy the having inner constraints.
Let's use again our example with Christmas electronics that is valid only between 1st and 24th December. To list all products available at 01:00 AM on October 1, 2023, issue a following query:
You can see that Christmas products like Retlux Blue christmas lightning, Retlux Warm white christmas lightning or Emos Candlestick are not present in the listing.
When you change the date and time in range constraint for validity attribute to 2nd December:
... you will see all those products in Christmas electronics category.
In the situation where the single product, let's say Garmin Vivosmart 5, is in both the excluded category Christmas Electronics and the included category Smartwatches, as on the following schematics:
Accessories category listing with validity constraintAccessories category listing with validity constraint

... it will remain in the query result because there is at least one product reference that is part of the visible part of the tree.

Excluding

The constraint
is a constraint that can only be used within hierarchyWithin or hierarchyWithinRoot parent constraints. It simply makes no sense anywhere else because it changes the default behavior of those constraints. Hierarchy constraints return all hierarchy children of the parent node or entities that are transitively or directly related to them, and the parent node itself.
The excluding constraint allows you to exclude one or more subtrees from the scope of the filter. This constraint is the exact opposite of the having constraint. If the constraint is true for a hierarchy entity, it and all of its children are excluded from the query. The excluding constraint is the same as declaring having(not(expression)), but for the sake of readability it has its own constraint.
The lookup stops at the first node that satisfies the constraint!
The hierarchical query traverses from the root nodes to the leaf nodes. For each of the nodes, the engine checks whether the excluding constraint is satisfied valid, and if so, it excludes that hierarchy node and all of its child nodes (entire subtree).
filterConstraint:+

one or more mandatory constraints that must be satisfied by all returned hierarchy nodes and that mark the visible part of the tree, the implicit relation between constraints is logical conjunction (boolean AND)

Self

When the hierarchy constraint targets the hierarchy entity, the children that satisfy the inner constraints (and their children, whether they satisfy them or not) are excluded from the result.

For demonstration purposes, let's list all categories within the Accessories category, but exclude exactly the Wireless headphones subcategory.
Accessories category listing excluding Wireless headphones subcategoryAccessories category listing excluding Wireless headphones subcategory
The category Wireless Headphones and all its subcategories will not be shown in the results list.

Referenced entity

If the hierarchy constraint targets a non-hierarchical entity that references the hierarchical one (typical example is a product assigned to a category), the excluding constraint is evaluated against the hierarchical entity (category), but affects the queried non-hierarchical entities (products). It excludes all products referencing categories that satisfy the excluding inner constraints.
Let's go back to our example query that excludes the Wireless Headphones category subtree. To list all products available in the Accessories category except those related to the Wireless Headphones category or its subcategories, issue the following query:
You can see that wireless headphone products like Huawei FreeBuds 4, Jabra Elite 3 or Adidas FWD-02 Sport are not present in the listing.
When the product is assigned to two categories - one excluded and one part of the visible category tree, the product remains in the result. See the example.

Author: Ing. Jan Novotný

Date updated: 5.5.2023

Documentation Source