evitaDB - Fast e-commerce database
logo
page-background

Facet filtering

Faceted filtering, also known as parameterized filtering, is a user interface feature that allows users to refine search results by applying multiple filters based on various properties or "facets" like category, parameter, or brand. Users can toggle these filters on or off to drill down into a data set interactively, essentially performing real-time complex queries without technical knowledge. The benefits are twofold: First, it improves user experience by enabling more targeted and efficient searching. Second, it can increase conversion rates for e-commerce sites by helping users quickly find and purchase products that meet their specific criteria.

Facet filter exampleFacet filter example

The key success factor of faceted search is to help users avoid situations where their filter combination returns no results. It works best when we gradually limit the facet options that don't make sense with the ones already selected, and also provide accurate, on-the-spot, real-time feedback about the number of results that will expand or limit the current selection when another facet is selected.

Facets are usually displayed as a list of checkboxes, radio buttons, drop-down menus, or sliders, and are organized into groups. The options within a group usually expand the current selection (logical disjunction), and the groups are usually combined with logical conjunction. Some of the facets can be negated (logical negation) to exclude results that match the facet option.

High cardinality facets are sometimes presented in the form of a search box or interval slider (sometimes with a histogram of the distribution of values) to allow users to specify the exact value or range of values they are looking for.
evitaDB supports all of the above forms of facet search using the operators documented in this chapter and in histogram.

evitaLab visualization

If you want to get more familiar with the facet summary calculation, you can try to play with the query and see how it affects the visualization tab you can find in our evitaLab console:
Facet summary visualization in the evitaLab consoleFacet summary visualization in the evitaLab console

The visualization is organized in the same way as the facet summary itself:

IconMeaning
ReferenceAt the top level, you can see the links marked with the chain icon.
Facet groupBelow them are the groups found within these reference types, marked with the group icon, and finally below the groups are the facet options themselves.
Results matching facetRepresents the number of entities returned that match this facet option when the user has no other facets selected (i.e., has an empty userFilter constraint).
Current number of results / difference when facet is selectedRepresents the current number of entities returned that match the filter constraints, next to the slash there is a difference in the number of results when this facet option is added to the user filter.
Total number of results with this facet selectedRepresents the total number of entities that will be displayed in the result when this facet option is selected (i.e., the number of entities that match the facet option in the entire dataset). )

Facet calculation rules

  1. The facet summary is calculated only for entities that are returned in the current query result (excluding the effect of userFilter part of the query if present)
  2. The calculation respects any filter constraints placed outside the userFilter container.
  3. The default relation between facets within a group is logical disjunction (logical OR).
  4. The default relation between facets in different groups / references is a logical AND.

Facet summary

argument:enum(COUNTS|IMPACT)?

Default: COUNTS

optional argument of type

that allows you to specify the computation depth of the facet summary:

  • COUNTS: each facet contains the number of results that match the facet option only
  • IMPACT: each non-selected facet contains the prediction of the number of results that would be returned if the facet option were selected (the impact analysis), this calculation is affected by the required constraints that change the default facet calculation behavior: conjunction, disjunction, negation.

filterConstraint:filterBy

optional filter constraint that limits the facets displayed and calculated in the summary to those that match the specified filter constraint.

filterConstraint:filterGroupBy

optional filter constraint that restricts the entire facet group whose facets are displayed and calculated in the summary to those that belong to the facet group matching the filter constraint.

orderConstraint:orderBy

optional order constraint that specifies the order of the facet options within each facet group

orderConstraint:orderGroupBy

optional order constraint that specifies the order of the facet groups

requireConstraint:entityFetch
optional requirement constraint that allows you to fetch the referenced entity body; the entityFetch constraint can contain nested referenceContent with an additional entityFetch / entityGroupFetch constraints that allows you to fetch the entities in a graph-like manner to an "infinite" depth
requireConstraint:entityGroupFetch
optional requirement constraint that allows you to fetch the referenced entity group body; the entityGroupFetch constraint can contain nested referenceContent with an additional entityFetch / entityGroupFetch constraints that allows you to fetch the entities in a graph-like manner to an "infinite" depth
The request triggers the calculation of the
containing the facet summary calculation. The calculated facet summary will contain all entity references marked as faceted in the entity schema. The facet summary can be further modified by the facet summary of reference constraint, which allows you to override the general facet summary behavior specified in the generic facet summary require constraint.
The faceted property affects the size of the indexes kept in memory and the scale / complexity of the general facet summary (i.e. the summary generated by the facetSummary request). It is recommended to mark only the references used for faceted filtering as faceted to keep the indexes small and the calculation of the facet summary in the user interface fast and simple. The combinatorial complexity of the facet summary is quite high for large datasets, and you may be forced to optimize it by narrowing the summary using the filtering facility or selecting only a few references for the summary.

Facet summary structure

The facet summary contains only entities referenced by entities returned in the current query response (excluding the effect of userFilter part of the query if present) and is organized in a three-tier structure:

1st tier: reference

For each entity reference marked as faceted in the facet summary, there is a separate data container for collection of the 2nd-tier facet groups. If the facets for this reference are not organized in groups (the reference lacks the group information), the facet summary will contain only one facet group named "non-grouped facets".

2nd tier: facet group

Facet group lists all facet options available for the given group and reference combination. It also contains a count of all entities in the current query result that match at least one facet in the group / reference.
Optionally, it can contain the body of the group entity if the entityGroupFetch requirement is specified.

There may also be a special "group" for facets that are not related to a group.

This group will be placed in the facet summary as a nonGroupedStatistics property.

3rd tier: facet

Facet contains the statistics for that facet option:

count

It represents the number of all entities in the current query result that match this facet (have reference to entity with this primary key).

requested
TRUE if this facet is requested in the user filter container of this query, FALSE otherwise (this property allows you to easily mark the facet checkbox as checked in the user interface).
And optionally the body of the facet (referenced) entity if the entityFetch requirement is specified. If the IMPACT statistics depth is requested in the facet summary, the statistics will also include the impact analysis calculation, which contains the following data:
matchCount
It represents the number of all entities that would match a new query derived from the current query if this particular facet option were selected (has reference to entity with this primary key). The current query is left intact, including the user filter part, but a new facet query is virtually added to the user filter to calculate the hypothetical impact of selecting the facet option.
difference
It represents the difference between the matchCount (hypothetical result should this facet be selected) and the current number of entities returned. It represents the size of the impact on the current result. It can be either positive (the facet option would expand the current result) or negative (the facet option would limit the current result). The difference can be 0 if the facet option doesn't change the current result.
hasSense
TRUE if the facet option combined with the current query still returns some results (matchCount > 0), FALSE otherwise. This property allows you to easily mark the facet checkbox as "disabled" in the user interface.
The
requirement triggers the calculation of the
extra result. The facet summary is always computed as a side result of the main entity query and respects any filtering constraints placed on the queried entities. To demonstrate the facet summary calculation, we will use the following example:

The query returns a list of "active" products in the "e-readers" category, and in the extra results index it also includes the facet summary calculation:

The format has been simplified because the raw JSON result would be too long and hard to read. This is the output format of the prettyPrint method of and you can see the summary organized in a three-tier structure, along with the information about the number of result entities for each of the facets and facet groups. No facet is currently selected and therefore the lead [ ] is not checked anywhere. The listing doesn't contain any human-readable information except the primary keys of the references, facet groups, and facets - to get them we would have to add their bodies.

Fetching facet (group) bodies

The facet summary makes little sense without the bodies of the facet groups and facets. To get those bodies, you need to add entityFetch or entityGroupFetch requirement to the query. Let's modify the example to fetch the facet summary along with the codes of the facets and their groups:

Now you can see that the facet summary contains not only the primary keys, but also the somewhat comprehensible codes of the facets and their respective groups:

If you add the desired locale to the query and also list localized names, you'll get a result that's very close to the version you want to see in the user interface:

Filtering facet summary

The facet summary sometimes gets very big, and besides the fact that it is not very useful to show all facet options in the user interface, it also takes a lot of time to calculate it. To limit the facet summary, you can use the filterBy and filterGroupBy (which is the same as filterBy, but it filters the entire facet group instead of individual facets) constraints.
If you add the filtering constraints to the facetSummary requirement, you can only refer to filterable properties that are shared by all referenced entities. This may not be feasible in some cases, and you will need to split the generic facetSummary requirement into multiple individual facetSummaryOfReference requirements with specific filters for each reference type.
It's hard to find a good example for filtering a generic facet summary even for our demo dataset, so the example will be a bit artificial. Let's say we want to display only the facet options whose code attribute contains the substring ar, and only those that are within groups with code starting with the letter o:

We don't limit the search to a specific hierarchy because the filter is quite selective, as you can see in the result:

Ordering facet summary

If you add the ordering constraints to the facetSummary requirement, you can only refer to sortable properties that are shared by all referenced entities. This may not be feasible in some cases, and you will need to split the generic facetSummary requirement into multiple individual facetSummaryOfReference requirements with specific ordering constraints for each reference type.

Let's sort both facet groups and facets alphabetically by their English names:

You can see that the facet summary is now sorted where appropriate:

Facet summary of reference

argument:string!
mandatory argument specifying the name of the reference that is requested by this constraint, the reference must be marked as faceted in the entity schema
argument:enum(COUNTS|IMPACT)

Default: COUNTS

optional argument of type

that allows you to specify the computation depth of the facet summary:

  • COUNTS: each facet contains the number of results that match the facet option only
  • IMPACT: each non-selected facet contains the prediction of the number of results that would be returned if the facet option were selected (the impact analysis), this calculation is affected by the required constraints that change the default facet calculation behavior: conjunction, disjunction, negation.

filterConstraint:filterBy

optional filter constraint that limits the facets displayed and calculated in the summary to those that match the specified filter constraint.

filterConstraint:filterGroupBy

optional filter constraint that restricts the entire facet group whose facets are displayed and calculated in the summary to those that belong to the facet group matching the filter constraint.

orderConstraint:orderBy

optional order constraint that specifies the order of the facet options within each facet group

orderConstraint:orderGroupBy

optional order constraint that specifies the order of the facet groups

optional requirement constraint that allows you to fetch the referenced entity body; the entityFetch constraint can contain nested referenceContent with an additional entityFetch / entityGroupFetch constraints that allows you to fetch the entities in a graph-like manner to an "infinite" depth
requireConstraint:entityGroupFetch
optional requirement constraint that allows you to fetch the referenced entity group body; the entityGroupFetch constraint can contain nested referenceContent with an additional entityFetch / entityGroupFetch constraints that allows you to fetch the entities in a graph-like manner to an "infinite" depth
The
requirement triggers the calculation of the
for a specific reference. When a generic facetSummary requirement is specified, this require constraint overrides the default constraints from the generic requirement to constraints specific to this particular reference. By combining the generic facetSummary and facetSummaryOfReference, you define common requirements for the facet summary calculation, and redefine them only for references where they are insufficient. The facetSummaryOfReference requirements redefine all constraints from the generic facetSummary requirement.
Let's say we want to display the facet summary for products in the e-readers category, but we want the summary to be computed only for the brand and parameterValues references. The facets within the brand reference should be ordered by name in alphabetical order, and the facets within the parameterValues reference should be ordered by their order attribute, both at the group level and at the facet level. Only the facets inside facet groups (parameter) with isVisible attribute equal to TRUE should be calculated for the summary:

As you can see, this is a fairly complex scenario that uses all the key features of the facet summary calculation:

Entity group fetch

The entityGroupFetch constraint used within the facetSummary or facetSummaryOfReference requirement is identical to the entityFetch requirement described in the referenced chapter. The only difference is that the entityGroupFetch refers to the related group entity schema specified by the faceted reference schema, and is named entityGroupFetch instead of entityFetch to distinguish the requirements for referenced (facet) entity and referenced (facet) entity group.

Entity fetch

The entityFetch constraint used within the facetSummary or facetSummaryOfReference requirement is identical to the entityFetch requirement described in the referenced chapter. The only difference is that the entityFetch refers to the related entity schema specified by the faceted reference schema.

Facet groups conjunction

argument:string!
Mandatory argument specifying the name of the reference to which this constraint refers.
filterConstraint:filterBy

Optional filter constraint that selects one or more facet groups whose facets will be combined with logical AND instead of the default logical OR.

If the filter is not defined, the behavior applies to all groups of a given reference in the facet summary.

The
changes the default behavior of the facet summary calculation for the facet groups specified in the filterBy constraint. Instead of logical disjunction (logical OR), the facet options in the facet groups are combined with logical conjunction (logical AND).
To understand the difference between the default behavior and the behavior of this requirement, let's compare the facet summary calculation for the same query with and without this requirement. We will need a query that targets some reference (let's say groups) and pretend that the user has already requested (checked) some of the facets. If we now want to calculate the IMPACT analysis for the rest of the facets in the group, we will see that changing the default behavior changes the numbers produced:
Note that the facetGroupsConjunction in the example doesn't contain a filterBy constraint, so it applies to all the facet groups in the facet summary, or in this particular case to facets in the reference groups that are not part of any group.
Default behaviourAltered behaviour
BeforeBeforeAfterAfter

You can see that instead of increasing the number of results in the final set, the impact analysis predicts their reduction:

Facet groups disjunction

argument:string!
Mandatory argument specifying the name of the reference to which this constraint refers.
filterConstraint:filterBy

Optional filter constraint that selects one or more facet groups whose facet options will be combined with logical disjunction (logical OR) with facets of different groups instead of the default logical conjunction (logical AND).

If the filter is not defined, the behavior applies to all groups of a given reference in the facet summary.

The
changes the default behavior of the facet summary calculation for the facet groups specified in the filterBy constraint. Instead of logical AND, the facet options in the facet groups are combined with logical OR with facets from different facet groups.
To understand the difference between the default behavior and the behavior of this constraint, let's compare the facet summary calculation for the same query with and without this constraint. We will need a query that targets some reference (let's say parameterValues) and pretend that the user has already requested (checked) some of the facets. Now, if we want to calculate the IMPACT analysis for the other group in the facet summary, we will see that instead of reducing the numbers, the impact analysis predicts their expansion:
Default behaviourAltered behaviour
BeforeBeforeAfterAfter

You can see that instead of reducing the number of results in the final set, the impact analysis predicts their expansion:

Facet groups negation

argument:string!
Mandatory argument specifying the name of the reference to which this constraint refers.
filterConstraint:filterBy

Optional filter constraint that selects one or more facet groups whose facet options are negated. Thus, instead of returning only those items that reference that particular faceted entity, the query result will return only those items that don't reference it.

If the filter is not defined, the behavior applies to all groups of a particular reference in the facet summary.

The
changes the behavior of the facet option in all facet groups specified in the filterBy constraint. Instead of returning only those items that have a reference to that particular faceted entity, the query result will return only those items that don't have a reference to it.
To demonstrate this effect, we need a query that targets some reference (let's say parameterValues) and makes some of the listed group as negated.
Default behaviourAltered behaviour
BeforeBeforeAfterAfter

The predicted results in the negated groups are far greater than the numbers produced by the default behavior. As you can see, selecting any option in the RAM facet group predicts returning thousands of results, while the ROM facet group with default behavior predicts only a dozen of them:

Author: Ing. Jan Novotný

Date updated: 29.10.2023

Documentation Source