evitaDB - Fast e-commerce database
logo
page-background

Query language

The article introduces the query language used in EvitaDB, covering syntax, querying multiple tables, filtering data, and aggregating data, with code examples.

The evitaDB query language is composed of a nested set of functions. Each function has its ow name and set of arguments inside round brackets (like this:function_name(arguments)), and any argument can be a plain value of a supported data type or other functions, arguments and functions are delimited by a comma (like this: argument1, argument2) and strings are enveloped by apostrophes (like this: 'this is string').
This language is expected to be used by human operators, because on the code level, the query is represented by a query object tree, that can be constructed directly without an intermediate string language form (on the contrary to an SQL language, which is strictly string typed). The human-readable form is used in this documentation. The human-readable form can be parsed to object representations using the parser.

The query has these four parts:

  • header: contains the entity (mandatory) specification
  • filter: contains the constraints limiting entities being returned (optional, if missing all are returned)
  • order: defines in what order will the entities return (optional, if missing entities are ordered by primary integer key in ascending order)
  • require: contains additional information for the query engine, may hold pagination settings, richness of the entities and so on (optional, if missing only primary keys of the entities are returned)
The query always returns results in the form of containing:
  • * of result data
  • A Map of extra results indexed by their class (<T extends EvitaResponseExtraResult> Map<Class<T>, T>), see detailed documentation for the individual require constraints producing extra results

Grammar

The grammar of the query is as follows:

Or a more complex one:

The filter, order and require constraints are optional, but the first argument specifying the entity type is mandatory. There may be at most one argument of these types: filterBy, orderBy, and require. Any of these arguments may be missing or may be swapped. I.e. the following query is still a valid query:
... or even this one (although, for better readability is recommended to maintain order of: entities, filterBy, orderBy, require):
This also means that there cannot be a constraint of the same name that could be used either in filtering or ordering or a require constraint. The constraint name uniquely identifies whether the constraint is a filter, order or a require constraint. The entity type is always a string.
The query must specify this entity. This mandatory string parameter controls what entity is targeted by the query.

Example usage:

Filter by

The constraint specifies, which entities will be returned from the entity collection. If an entity doesn't fulfill all the constraints within this constraint, it's not returned by the query engine.

Example usage:

These are the constraint functions that can be used in the filter:

And

The and constraint is the container constraint. It contains two or more inner constraints, whose output is combined by logical AND.

Example usage:

Or

The or contstraint is also a container constraint. It contains two or more inner constraints, whose output is combined by logical OR.

Example usage:

Not

The not constraint is yet another container constraint. It contains a single inner constraint, whose output is negated. Behaves as logical NOT.

Example usage:

Equals

The equals constraint compares the value of the attribute whose name passed in the first argument with the value passed in the second argument. The first argument must be a string, the second argument can be anything of the Comparable type. The type of the attribute value and the second argument must be convertible one to another, otherwise, the equals function returns false.

The function returns true, if both values are equal.

Example usage:

This function supports attribute arrays. When an attribute value is of the array type, the equals function returns true if any of the attribute array element values equal the value in the constraint.

Example usage:

If we have the attribute code with the value ['A','B','C'], all these constraints will match:

Greater than

The greaterThan constraint compares value of the attribute with it's name passed in the first argument with the value passed in the second argument. The first argument must be a string, the second argument may be any comparable type. The type of the attribute value and second argument must be convertible to one another, otherwise the greaterThan function returns false.

The function returns true, if the value in a filterable attribute of such a name is greater than the value in the second argument.

This function currently doesn't support attribute arrays, and when an attribute is of the array type, the query returns an error. This may, however, change in the future.

Example usage:

Greater than, equals

The greaterThanEquals constraint compares the value of the attribute with it's name passed in the first argument with the value passed in the second argument. The first argument must be a string, the second argument can be any Comparable type. The type of the attribute value and second argument must be convertible one to another, otherwise the greaterThanEquals function returns false.

The function returns true, if a value in a filterable attribute of such a name is greater than the value in the second argument or equal.

This function currently doesn't support attribute arrays, and when an attribute is of the array type, the query returns an error. This may, however, change in the future.

Example usage:

Less than

The lessThan constraint compares the value of the attribute with its name passed in first argument, and with the value passed in the second argument. The first argument must be a string, the second argument can be any comparable type. This type of the attribute value and second argument must be convertible to one another, otherwise, the lessThan function returns false.

The Function returns true, if the value in a filterable attribute of such a name is of a lesser value than the in second argument.

This function currently doesn't support attribute arrays, and when an attribute is of the array type, the query returns an error. This may however change in the future.

Example usage:

Less than, equals

The lessThanEquals constraint compares the value of the attribute with name passed in the first argument with the value passed in the second argument. The first argument must be a string, the second argument be any Ccomparable type. The type of the attribute value and second argument must be convertible to one another, otherwise the lessThanEquals function returns false.

The function returns true, if the value in a filterable attribute of such a name is of lesser value than the one in the second argument or equal.

This function currently doesn't support attribute arrays, and when an attribute is of the array type, the query returns an error. This may, however, change in the future.

Example usage:

Between

The between constraint compares the value of the attribute with its name passed in the first argument with the value passed in the second argument, and a value passed in the third argument. The first argument must be a string, the second and third argument may be any comparable type. Type of the attribute value and second argument must be convertible to one another, otherwise, the between function returns false.

The function returns true, if the value in a filterable attribute of such a name is greater than or equal to the value in second argument, and lesser than or equal to the value in third argument.

Example usage:

This function supports attribute arrays, and when an attribute is of the array type, the between function returns true, providing any of the attribute array element values is between the passed interval.

Example usage:

If we have the attribute amount with a value of [1, 9], all of these constraints will match:
If an attribute is of the type, the between constraint behaves like an overlap - it returns true, if the examined range and any of the attribute ranges (see previous paragraph about array type behaviour) share anything in common.

Behaviour of between with range type example:

All of the following constraints return true, when we have the attribute validity with the following values: [[2,5],[8,10]]:

... but these constraints will return false:

In set

The inSet constraint compares the value of the attribute with the name passed in the first argument with all of the values passed in the second, third and any other additional arguments. The first argument must be a String, additional arguments can be any Comparable type. The type of the attribute value and any additional arguments must be convertible to one another, otherwise the inSet function skips the value comparison and ultimately returns false.

The function returns true if an attribute value is equal to at least one of the additional values.

Example usage:

The function supports attribute arrays, and when an attribute is of the array type, inSet returns true, providing that any of the attribute array element values equal the value in the constraint.

Behaviour of inSet with array type example:

If we have the attribute code with the value ['A','B','C'], all these constraints will match:

Contains

The contains constraint searches the value of the attribute with the name passed in the first argument for the presence of the String value passed in the second argument.
The function returns true, if the attribute value contains a secondary argument (starting on any position). The function is case-sensitive and the comparison is executed using UTF-8 encoding (Java native).

Example usage:

This function supports attribute arrays and when an attribute is of the array type, the contains function returns true, providing that any of the attribute array element values contain the value in the constraint.

Behaviour of contains with array type example:

If we have the attribute code with the value ['cat','mouse','dog'], all these constraints will match:

Starts with

The startsWith constraint searches the value of the attribute with its name passed in first argument for the presence of the String value passed in the second argument.
The Function returns true, if the attribute value contains the secondary argument (starting on first position). In other words, if the attribute value starts with string passed in second argument. The function is case-sensitive, and the comparison is executed using UTF-8 encoding (Java native).

Example usage:

This Function supports attribute arrays, and when an attribute is of the array type, the startsWith function returns true providing any of the attribute array element values start with the value in the constraint.

Behaviour of startsWith with array type example:

If we have the attribute code with the value ['cat','mouse','dog'], all these constraints will match:

Ends with

The endsWith constraint searches the value of the attribute with name passed in first argument for presence of the String value passed in the second argument.
The function returns true, if an attribute value contains a secondary argument (using reverse lookup from the last position). In other words, if the attribute value ends with a string passed in second argument. The function is case-sensitive, and comparison is executed using UTF-8 encoding (Java native).

Example usage:

The function supports attribute arrays, and when an attribute is of the array type, the endsWith function returns true, providing any of the attribute array element values end with the value in the constraint.

Behaviour of endsWith with array type example:

If we have the attribute code with the value ['cat','mouse','dog'], all these constraints will match:

Is true

The isTrue constraint compares the value of the attribute with name passed in the first argument with the boolean TRUE value. The first argument must be a String. The type of the attribute value must be convertible to boolean, otherwise the isTrue function returns false.
The function returns true, if the attribute value equals to a Boolean#TRUE.

Example usage:

The function supports attribute arrays, and when an attribute is of the array type, the isTrue function returns true, providing any of the attribute array element values are equal to true.

Behaviour of isTrue with array type example:

If we have the attribute dead with the value ['true','false'], both isTrue and isFalse match. Hence, we can call this attribute Schrödinger one - both dead and undead. In other words, this constraint will work even if it doesn't make a lot of a sense.

Is false

The isFalse constraint compares the value of the attribute with its name passed in first argument with the boolean FALSE value. The first argument must be a String. The type of the attribute value must be convertible to booleanm, otherwise, the isFalse function returns false.
The function returns true if the attribute value equals to Boolean#FALSE.

Example usage:

The function supports attribute arrays, and when an attribute is of the array type, the isFalse function returns true, providing any of the attribute array element values are equal to false.

Behaviour of isFalse with array type example:

If we have the attribute dead with the value ['true','false'], both isTrue and isFalse match. Hence, we can call this attribute Schrödinger one - both dead and undead. In other words, this constraint will work even if it doesn't make a lot of a sense.

Is null

The isNull constraint checks the existence of a value of the attribute with its name passed in first argument. The first argument must be a String. The attribute of such name must not exist, and if it doesn't, the isNull function returns true.

The function returns true if the attribute doesn't exist.

Example usage:

Function supports attribute arrays in the same way as plain values.

Is not null

The isNotNull constraint checks for the existence of a value of the attribute with its name passed in first argument. The first argument must be String. The attribute of such name must exist, and if it does, the isNotNull function returns true.

The function returns true if the attribute exists.

Example usage:

The function supports attribute arrays in the same way as plain values.

In range

The inRange constraint compares the value of the attribute with its name passed in the first argument with the date and time value passed in the second argument. the first argument must be a String, the second argument must be a type.

The function returns true, if the second argument is greater than or equal to the range start (from), and is lesser than or equal to the range end (to).

Example usage:

The function supports attribute arrays, and when an attribute is of the array type, the inRange function returns true, providing any of the attribute array element values have a range that envelopes the passed value in the constraint.

Behaviour of inRange with array type example:

If we have the attribute age with the value [[18, 25],[60,65]], all of these constraints will match:

Primary key

The primaryKey constraint that accepts a set of int values, representing primary keys of the entities, that should be returned.

The function returns true, if entity primary key is equal to any one of the passed set of integers.

This kind of entity lookup function is the fastest one. If you have primary keys available, use them for querying preferably.

Example usage:

Language

The language constraint only accepts a single Locale argument.

The function returns true, if the entity has at least one localized attribute or associated data using the specified locale.

If the require constraint part of the query doesn't contain the dataInLanguage requirement constraint, that would specify the requested data localization, this filtering constraint implicitly sets requirement to the passed locale argument. In other words, if the entity has two localizations: en-US and cs-CZ, and the language('cs-CZ') constraint is used in query, the returned entity would only have the cs-CZ localization of attributes and associated data fetched along with it (and also attributes that are locale agnostic).
If a query contains no language constraint, the filtering logic is applied only on "global" (i.e. language agnostic) attributes.
Only a single language constraint can be used in the query.

Example usage:

Price in currency

The priceInCurrency constraint only accepts a single String argument that represents currency in an ISO 4217 code.
The function returns true, if the entity has at least one price with the specified currency. This function is also affected by the priceInPriceLists function, limiting the examined prices as well.
If the require constraint part of the query doesn't contain any prices requirement constraints that would specify the requested price currency, this filtering constraint implicitly sets requirement to the passed currency argument. In other words, if the entity has prices with two currencies: USD and CZK, and the priceInCurrency('CZK') constraint is used in the query, the returned entity would only have CZK prices fetched along with it.
Only a single priceInCurrency constraint can be used in the query.

Example usage:

Price in price lists

The priceInPriceLists constraint accepts one or more String arguments representing names (or any other unique identifiers) of the price lists. The price list is a key for distinguishing multiple prices of a single entity.
The function returns true, if the entity has at least one price in any of the specified price lists. This function is affected by the priceInCurrency function, limiting the examined prices as well. The order of the price lists passed in the argument is crucial, because it defines the priority of the price lists.

Behaviour of priceInPriceLists regarding the price list priority:

Let's have a product with following prices:

priceListcurrencypriceWithTax
basicEUR999.99
registered_userEUR979.00
b2c_discountEUR929.00
b2b_discountEUR869.00

If the query contains:

The product will not be found - because the query engine will use the first defined price for the price lists in the defined order. In our case, it's the price 999.99, which is not in the defined price interval €800-€900. If the price lists in the argument gets switched to priceInPriceLists('b2b_discount', 'basic'), the product will be returned, because the first price is now from the b2b_discount price list - €869, and this price is within the defined interval.
If the require constraint part of the query doesn't contain a prices requirement constraint that would specify the requested price lists, this filtering constraint implicitly sets the requirement to the passed price list argument. In other words, if the entity has two prices - one from the price list basic, second from price list b2b, and the priceInPriceLists('basic') price list is used in the query, the returned entity would only have the first price for the basic price list fetched along with it.
The non-sellable prices are not taken into account in the search - if the entity only has non-sellable prices, it will never be returned when the priceInPriceLists constraint or any other price constraint is used in the query. Non-sellable prices behave as if they don't exist. These non-sellable prices still remain accessible for reading on the fetched entity, in case the product is found by a sellable price satisfying the filter. If you have a specific price list reserved for non-sellable prices, you may still use it in the priceInPriceLists constraint. It won't affect the set of returned entities, but it will ensure you can access those non-sellable prices on entities even when the RESPECTING_FILTER in prices requirement constraint is used.
Only a single priceInPriceLists constraint can be used in the query.

Example usage:

Price valid in time

The priceValidIn constraint accepts a single OffsetDateTime argument representing the moment in time for which the entity price must be valid. The argument may be missing, and if so, the current date and time (now) will be used instead.
The function returns true, if the entity has at least one sellable price, and if the price's validity (valid from) is lesser or equal to the passed date and time, and the validity end (valid to) is greater than or equal to the passed date and time. This function is affected by the priceInCurrency and the priceInPriceLists functions, limiting the examined prices as well.
If the require constraint part of the query doesn't contain a prices requirement constraint that would specify the requested price lists, this filtering constraint implicitly sets the requirement to the passed price list argument. In other words, if entity has two prices - one valid from tomorrow, and the second one valid until tomorrow, and priceValidIn() is used in the query (using the now moment implicitly), the returned entity would only have the first price for valid now fetched along with it.
Only a single priceValidIn constraint can be used in the query. The validity of the prices will not be taken into an account when priceValidIn is not used in the query.

Example usage:

Price between

The priceBetween constraint accepts two BigDecimal arguments representing lower and higher price bounds (inclusive).
The function returns true, if entity has a sellable price in most prioritized price list according to the priceInPriceLists constraint greater than or equal to the passed lower bound, and lesser than or equal to the passed higher bound. This function is affected by other price related constraints, such as the priceInCurrency functions limiting the examined prices as well.
The most prioritized price term relates to the price computation algorithm described in a separate article. Non-sellable prices doesn't participate in the filtering at all.
By default, the price with tax is used for filtering, but you can change this by using the queryPriceMode require constraint.
Only a single priceBetween constraint can be used in the query.

Example usage:

Facet

The facet constraint accepts a String entity type in first argument,and one or more additional int arguments that represent references the entity is required to have in order to match this constraint.

The function returns true, if an entity has a facet (faceted reference) for the specified reference name matching any of the passed primary keys in the additional arguments. In other words, the entity references, whose primary key is equal to any of the passed primary keys.

Example usage:

The constraint should be used in a user filter container because it represents the user selection, which is considered as optional by the search engine in certain cases. See the detailed description of the user filter constraint container for more information.

By default, facets of the same type within the same group are combined by disjunction (OR) and facets of different reference names / groups are combined by conjunction (AND). This default behaviour can be surgically controlled by using any of the following require constraints:

The reason is simple - facet relations in certain groups are usually specified system-wide, and don't change in time frequently. This means that it could be easily cached, and passing this information in an extra require simplifies the query construction process.

Another reason is that we need to know the relationships among facet groups even for types/groups that haven't yet been selected by the user in order to compute the facet summary output.

Reference having attribute

The referenceHavingAttribute constraint container filters returned entities by attributes specified in their reference relations. The attributes in the relation specified by the first String argument of this container must match the filtering constraints specified in any additional arguments.

Example usage:

or

Example usage:

In order to filter by attributes specified on reference relations, both the reference schema itself and the attribute must be marked as "filterable", otherwise an error is returned.

Within hierarchy and within root hierarchy

The withinHierarchy constraint accepts a String reference name in the first argument, a primary key of the int type of entity with hierarchical placement in the second argument. There are also optional additional arguments - see constraints directRelation, excluding root and excluding for more information.
If you query an entity schema that is hierarchical itself (see hierarchical placement), you need to use just one numeric argument representing the primary key of the parent entity in an int. This format of the constraint usage may be used ,for example, for returning a category subtree (where we want to return category entities and also filter them by their own hierarchy placement).
The function returns true, if entity has at least one reference relating to the specified reference name either directly or transitively to any other reference with hierarchical placement subordinate to the directly related entity placement (in other words is present in its subtree).

Example usage:

Let's have the following hierarchical tree of categories (primary keys are in brackets):

  • TV (1)
    • Crt (2)
    • LCD (3)
      • big (4)
      • small (5)
    • Plasma (6)
  • Fridges (7)

When the following query targeting product entities is used:

only the products that relate directly to the categories: TV, Crt, LCD, big, small and Plasma will be returned. Products in Fridges will be omitted, because they are not in a subtree of the TV hierarchy.
Only a single withinHierarchy constraint can be used in the query.

If you want to constraint the entity that you're querying on, you need to omit the reference specification.

Querying the same entity type:

This query will return all the categories that belong to the subtree of category with a primary key equal to 5.

If you want to list all entities from the root level you need to use a different constraint - withinRootHierarchy using the same notation, but omitting the primary key of the root level entity

Querying the same entity type from root level:

This query will return all of the categories within the CATEGORY entity.

Querying the different entity type from root level:

You may use this constraint to list entities that refers to the hierarchical entities:

This query returns all the products that are attached to any category. Although, this query doesn't make much sense itself, it starts to be useful when it's combined with additional inner constraints described in the following paragraphs.

You can use additional sub constraints the in withinHierarchy or withinRootHierarchy constraints:

Direct relation

The directRelation constraint can be used only as sub constraint of withinHierarchy or withinRootHierarchy. Using this constraint in the query ensures that only the entities directly referencing the matching hierarchy entity will be returned. In other words, the transitive references (subtree) will not match the parent constraint filter.

Let's have the following category tree related by following products:

  • TV (1):
    • Product Philips 32"
    • Product Samsung 24"
    • Crt (2):
      • Product Ilyiama 15"
      • Product Panasonic 17"
    • LCD (3):
      • Product BenQ 32"
      • Product LG 28"
      • AMOLED (4):
        • Product Samsung 32"

When using this query:

All products will be returned.

When this query is used:

Only products directly related to TV category will be returned - i.e.: Philips 32" and Samsung 24". Products related to sub-categories of TV category will be omitted.

You can also use this hint to browse the hierarchy of the entity itself - to fetch subcategories of category. If you use this query:

All categories under the category subtree of TV will be listed (this means categories TV, Crt, LCD, AMOLED).

If you use this query:

Only direct sub-categories of category TV will be listed (this means categories Crt and LCD).

Filtering root categories only (entity itself) example:

If you need to filter the root categories only, you can use following query:

Notice that the previous example doesn't make sense for querying any entities of a different type than the hierarchical entity itself. This query:

will never return any product, because no product can relate the "virtual" super root of category entity. Products will always target some existing category entity and this means that only the withinHierarchy constraint makes any sense in this case.

Excluding root

The excludingRoot constraint can only be used as sub constraint of withinHierarchy or withinRootHierarchy. Using this constraint in the query ensures that all the entities referencing the matching hierarchy entity, will be omitted from the query result.

Example usage:

Let's have the following category tree with products referencing them:

  • TV (1):
    • Product Philips 32"
    • Product Samsung 24"
    • Crt (2):
      • Product Ilyiama 15"
      • Product Panasonic 17"
    • LCD (3):
      • Product BenQ 32"
      • Product LG 28"

When using this query:

all the products will be returned.

When this query is used:

Only products related to sub-categories of the TV category will be returned - i.e.: Ilyiama 15", Panasonic 17" and BenQ 32", LG 28". The products related directly to tee TV category will not be returned.
The excludingRoot constraint doesn't make sense to be used within the withinRootHierarchy. As you can see, the excludingRoot and directRelation constraints are mutually exclusive, and should not be used together within the same parent hierarchy constraint.

Excluding

The excluding constraint can be used only as sub constraint of withinHierarchy or withinRootHierarchy. Using this constraint in the query ensures that all the entities referencing the matching hierarchy entity or transitively any of its subordinate entities (subtree), will be omitted from the query result. It accepts one or more int primary keys that mark the hierarchy's "relative" roots, whose subtrees should be omitted from the result.

Exclusion arguments allow or the excluding of certain parts of the hierarchy tree from examination. This constraint comes handy when the catalog implementation allows for the making of categories that are "invisible" for some end users while keeping those categories for different kinds of users accessible.

Example usage:

Let's have the following hierarchical tree of categories (primary keys are in brackets):

  • TV (1)
    • Crt (2)
    • LCD (3)
      • big (4)
      • small (5)
    • Plasma (6)
  • Fridges (7)

When the following query is used:

only the categories TV, Crt, Plasma will be returned. The category Fridges will be omitted, because it isn't present within TV hierarchy tree. The category LCD and its sub-categories will be omitted due to the excluding constraint.

Excluding subtree example for different entity:

Let's have the following category tree with products referencing them:

  • TV (1)
    • Crt (2)
      • Product Philips 32"
      • Product Samsung 24"
    • LCD (3)
      • Product BenQ 32"
      • big (4)
        • Product Panasonic 40"
      • small (5)
        • Product Ilyiama 15"
    • Plasma (6)
      • Product LG 28"
  • Fridges (7)

When using this query:

only the Philips 32", Samsung 24" and LG 28" will be returned. The products in Fridges will be omitted because they are not in a subtree of the TV hierarchy and products directly related to the LCD category or any other sub-category will be omitted because they're part of the excluded subtrees of the excluding constraint.

User filter

The userFilter constraint container could contain any constraint except priceInPriceLists, language, priceInCurrency, priceValidInTime and within hierarchy, which make no sense to be directly set by the end user and affect the overall evaluation of the query. All the constraints placed directly inside userFilter are combined with by conjunction (AND).
The constraints placed in the userFilter container should react to the filter selection defined by the end user, and must be isolated from the base filter so that the facetSummary and histogram logic can distinguish a mandatory filtering constraint for a facet summary computation from the optional user defined one. The facet summary must compute a so-called baseline count - i.e. the count of the entities that match system constraints excluding the currently set filter of the end user. Similar logic also applies to histogram computation, where the selection applied on the attribute the histogram takes the data from must not be taken into an account.
Only single userFilter constraint can be used in the query.

Example usage:

Complex Example usage:

Even more complex queries are supported (although it is hard to make up some real life example for such):

The userFilter constraint might be a subject to change and affects advanced searching queries (not planned to be implemented in the research implementations) such as exclusion facet groups (i.e. facet in group are not represented as multi-select/checkboxes but as exclusive select/radio), or conditional filters (which can be used to apply a certain filter only if it would produce a non-empty result, this is good for "sticky" filters).

Hints for implementation

The user filter envelopes the part of the query that is affected by user selection and that is optional. All constraints outside user filter are considered mandatory and must never be altered by the facet summary computational logic.
The base count of the facets are computed for a query having the userFilter container contents stripped off. The "what-if" counts requested by the impact argument are computed from the query including a userFilter, creating multiple sub-queries and checking the result for each additional facet selection.
Facet filtering constraints must be direct children of the userFilter container. Their relationship is by default as follows: facets of the same type within same group are combined by disjunction (OR)- and facets of different types / groups are combined by conjunction (AND). This default behaviour can be surgically controlled by using any of the following require constraints:
The constraints different from the facet filtering constraints (as seen in example) can represent user conditions in non-faceted inputs, such as interval inputs.

Order by

The ordering constraints specify in what order entities will be returned from the entity collection. If the entity has no valid value requested by ordering, secondary, tertiary and other order constraints are taken into account when primary filtering is all sorted out. When no ordering can be applied to an entity, it'll be appended to the end of the result in ascending order of its primary key.

An evita DB sample ordering might look like this:

The ordering process goes as follows:

  • the first ordering is evaluated, entities missing the requested attribute value are moved to an intermediate bucket
  • the next ordering is evaluated using entities present in an intermediate bucket, entities missing the requested attribute are moved to a new intermediate bucket
  • the second step is repeated until all orderings are processed
  • the content of the last intermediate bucket is appended to the result ordered by the primary key in ascending order
Entities with the same (equal) values must not be subject to secondary ordering rules and may be sorted randomly within the scope of entities with the same value (this is subject to change; this behaviour differs from the one used by relational databases - but might be more performant). See issue #11 for planned changes in this area.

The array type attributes don't support sorting.

Ordering functions that can be used in the order by the constraint container are these:

Ascending

The ascending ordering constraint sorts returned entities by values in the attribute with the name passed in the first argument in ascending order. The argument must be of the String type. The ordering is executed by natural order of the Comparable type.

Example usage:

Descending

The descending ordering constraint sorts the returned entities by values in an attribute with the name passed in the first argument in descending order. The argument must be of the String type. The ordering is executed by reversed natural order of the Comparable type.

Example usage:

Price ascending

The priceAscending ordering constraint sorts returned entities by price for sale in ascending order. The price for sale is computed by an algorithm described in separate chapter.

Example usage:

Price descending

The priceDesscending ordering constraint sorts returned entities by price for sale in descending order. The price for sale is computed by the algorithm described in separate chapter.

Example usage:

Random

The random ordering constraint sorts returned entities in random order.

Example usage:

Reference attribute

The referenceAttribute ordering constraint container sorts the returned entities by reference attribute. The name of the reference is specified in the first String argument, the ordering for the attribute is specified in additional argument(s). Price related orderings cannot be used here, because the references don't possess prices.

Example usage:

or

Usage example with multiple ordering constraints:

Require

The require constraints specify additional behaviour of the query interpretation or completeness of the returned entities. Some require constraints trigger the computation of additional data upon returned entities. There is a valid expectation that the derived statistics computed along with result of the original query will be computed much faster compared to a situation where they are collected and computed in multiple separate queries. This expectation comes from the idea that within the same query, the engine could take advantage of shared intermediate results, and avoid repeated work otherwise necessary in isolated queries.

When no require constraint is used, the primary keys of the first 20 entities matching the passed query are returned, ordered by their primary key in ascending order.

A sample evitaDB query with the require constraint might look like this:

The functions that can be used in the require container are these:

Page

The page constraint controls the count of entities in the query output. It allows for specifying 2 arguments in the following order:
  • int pageNumber: The number of the page of results that are expected to be returned, starts with 1, must be greater than zero (mandatory)
  • int pageSize: The number of entities on a single page, must be greater than zero (mandatory)

Return first page with 24 items:

Strip

The strip constraint controls the count of entities in the query output. It allows specifying 2 arguments in the following order:
  • int offset: The number of the items that should be omitted in the result, must be greater than or equals to zero (mandatory)
  • int limit: The number of entities that should be returned, must be greater than zero (mandatory)

Return 24 records from index 52:

Entity body

The entityBody constraint changes the default behaviour of the query engine, only returning entity primary keys in the result. When this require constraint is used, the result contains entity bodies, except attributes, associated data, references and prices. These types of data can be fetched either lazily or by specifying additional require constraints (attributes, associatedData, references, prices) in the query.

Example usage:

Attributes

The attributes require constraint changes the default behaviour of the query engine returning only entity primary keys in the result. When this require constraint is used, the result contains entity bodies along with attributes. Other parts of the entity (associated data, references and prices) fetching react to similar requirement constraints, but are not related to this one.
The attributes require constraint implicitly triggers an entity fetch, because attributes cannot be returned without its entity container. Localized attributes are returned according to the data in language requirement constraint, or language filtering constraint, if the requirements don't declare it.

Example usage:

Prices

The prices require constraint changes the default behaviour of the query engine, only returning the entity primary keys in the result. When this require constraint is used, the result contains entity prices. Other parts of the entity (attributes, associated data and references) fetching react to similar requirement constraints, but are not related to this one.
This require constraint implicitly triggers an entity require, because prices cannot be returned without its entity container. By default, the fetched prices are filtered according to price filtering constraints, should they have been used in the query. This behaviour might be changed, by a single optional argument of this requirement constraint.
The constraint accepts a single optional argument with following options:
  • ALL: all prices of the entity are returned regardless of the input query constraints, otherwise, prices are filtered by those constraints
  • RESPECTING_FILTER (default): only prices that match query filter will be returned along with the entity
  • NONE: no prices will be returned along with entity

Example usage:

Associated data

The associatedData require constraint changes default behaviour of the query engine, only returning the entity primary keys in the result. When this require constraint is used, the result contains entity bodies along with associated data). Other parts of the entity (attributes, references and prices) fetching react to similar requirement constraints, but are not related to this one.
The associatedData require constraint implicitly triggers an entity fetch, because associated data cannot be returned without its entity container. Localized associated data is returned according to the data in language requirement constraint, or the language filtering constraint, if the requirements don't declare it.
The constraint accepts one or more String arguments that refer to the associated data names that should be fetched along with the entity. If no argument is passed to the constraint - all associated data is fetched along. Because the associated data is expected to be quite heavy, we recommend to always fetch selected associated data by their name explicitly and avoid fetching them all at once.

Example usage:

References

The references require constraint changes default behaviour of the query engine, only returning the entity primary keys in the result. When this require constraint is used, result contains entity bodies along with references to any internal or external entity types specified in one or more arguments of this require constraint. Other parts of the entity (attributes, associated data and prices) fetching react to similar requirement constraints, but are not related to this one.
This require constraint implicitly triggers an entity body require, because the references cannot be returned without its container entity.

References are always returned with all their attributes (i.e. attributes set on this particular relation to the entity).

The constraint accepts one or more String arguments that refer to the reference data names that should be fetched along with the entity. If no argument is passed to the constraint - all references are fetched along. Because the references are expected to be quite heavy, we recommend to always fetch selected references by their name explicitly and avoid fetching them all at once.

Example usage:

Data in language

The dataInLanguage require constraint accepts zero or more Locale arguments. If the result requires returning entity bodies along with attributes and associated data, these data will contain both global data and localized ones. The localization of the data will respect the arguments of this requirement constraint.

If constraint contains no argument, data localized to all languages is returned.

If neither the dataInLanguage require constraint, nor the language filtering constraint is present in the query, only global attributes and associated data is returned.
Only a single dataInLanguage constraint can be used in the query.

Fetching global attributes and attributes localized to English:

If you only need to fetch global and en-US localized attributes and associated data, (considering there are multiple language localizations):

Fetching data in all available locales:

The following requirement fetches all of the available global and localized data:

Use of price

The useOfPrice require constraint can be used to control the form of prices that will be used for computation in the priceBetween filtering, and price ascending/descending ordering. Also, price histogram is sensitive to this setting. By default, the end customer form of price (e.g. price with tax) is used in all of the above-mentioned constraints. This could be changed by using this requirement constraint. It has a single String argument that can have one of the following values:
  • WITH_TAX (default)
  • WITHOUT_TAX

Example usage:

Parents

The parents require constraint can be used in relation with hierarchical entities, and targets the entity type that is requested by the query. The constraint can also have inner require constraints that define how rich the returned information should be (by default, only the primary keys are returned, but full entities can be returned as well).
When this require constraint is used, an additional object of the type is stored to result the index. This data structure contains any information about the referenced entity paths for each entity in the response.

Example usage:

An example for returning the parents of the same type as was queried (e.g. parent categories of filtered categories):

Usage example returning full bodies of parent entities:

Any additional data structures, by default, only return the primary keys of those entities, but it can also provide full parent entities when this form of constraint is used:

Parents of type

The parentsOfType require constraint can be used in relation with hierarchical entities, and can have one or more String arguments that specify the reference name of any hierarchical entity that this entity relates to. The constraint can also have inner require constraints that define how rich the returned information should be (by default, only the primary keys are returned, but full entities can be returned as well).
When this require constraint is used, an additional object of the type is stored to the result index. This data structure contains any information about the referenced entity paths for each entity in the response.

Example usage:

The following query returns the parents of the category when the entity type product is queried:

Usage example returning full bodies of parent entities:

Any additional data structures ,by default, only return primary keys of those entities, but it can also provide full parent entities when this form of constraint is used:

Facet summary

The facetSummary requirement constraint triggers the computing and adding of an object of the type to the result index. The data structure is quite complex, but it allows for the rendering of an entire facet listing to end users. It contains information about all the facets present in the current hierarchy view, along with count of requested entities that have those facets assigned.
The facet summary respects the current query filtering constraints, excluding the conditions inside the userFilter container constraint.
The constraint optionally accepts a single String argument:
  • COUNT (default): only counts of facets will be computed
  • IMPACT: counts and selection impact for non-selected facets will be computed

Example usage:

Facet groups conjunction

The facetGroupsConjunction require constraint allows for the specifying of inter-facet relations inside of facet groups identified by primary keys in the arguments of this constraint. First, a mandatory String argument specifies the reference name of the facet reference. The secondary argument allows you to define one or more primary keys of the referenced group ids, which the inner facets should consider conjunctive.
This require constraint changes the default behaviour, stating that all facets inside the same facet group are combined by an OR relation (eg. disjunction). The constraint makes sense only when a facet or a facet summary constraint is part of the query.

Example usage:

This statement means, that facets in the parameters reference and collected in groups with the primary key 1, 8, 15, will be joined with a boolean (AND) relation when selected.

Let's have this facet/group situation:

Color parameters (group id: 1):
  • blue (facet id: 11)
  • red (facet id: 12)
Size parameters (group id: 2):
  • small (facet id: 21)
  • large (facet id: 22)
Flags tag (group id: 3):
  • action products (facet id: 31)
  • new products (facet id: 32)
When the user selects the facets: blue (11), red (12), by default, the relation would be:
get all entities with facet blue(11) OR facet red(12)
If the require constraint facetGroupsConjunction('parameters', 1) is passed in the query, the filtering condition will be composed differently. It will be composed as follows:
get all entities with facet blue(11) AND facet red(12)

Facet groups disjunction

The facetGroupsDisjunction require constraint allows for the specifying of any facet relations among different facet groups of certain primary keys. First, a mandatory String argument specifies the name of the reference, whose group behaviour is altered. The secondary argument allows you to define one more facet group primary keys, which should be considered disjunctive.
The facetGroupsDisjunction require constraint changes the default behaviour, stating that facets between two different facet groups are combined by an AND relation and changes it to a disjunction (OR) relation instead.

Example usage:

This statement means, that facet groups with the primary key 1, 2 in the parameters reference, will be joined with a boolean (OR) relation when selected.

Let's have this facet/group situation:

Color parameters (group id: 1):
  • blue (facet id: 11)
  • red (facet id: 12)
Size parameters (group id: 2):
  • small (facet id: 21)
  • large (facet id: 22)
Flags tag (group id: 3):
  • action products (facet id: 31)
  • new products (facet id: 32)
When the user selects facets: blue (11), large (22), new products (31) - the default meaning would be:
get all entities with blue(11) AND large(22) AND new products(31)
If this require constraint: facetGroupsDisjunction('tag', 3) is passed in the query, the filtering condition will be composed as:
get all entities with (blue(11) AND large(22)) OR new products(31)

Facet groups negated

The facetGroupsNegation require constraint allows you to declare a reverse impact of a facet selection in facet groups with specified primary keys. Negative facet selection groups cause the omitting of all entities that have requested a facet in a query result. First, a mandatory String argument specifies the name of the reference, whose group behaviour is altered. The secondary argument allows for the defining of one more facet group primary keys that should be considered negative.

Example usage:

This statement means that facets in groups with the primary key 1, 8, 15 in the parameters reference will be joined with a boolean AND NOT relation when selected.

Attribute histogram

The attributeHistogram require constraint, when used, triggers the computation and the adding of an object of the type, allowing you to render histograms to the query response.
In the first int argument, it expects the number of histogram buckets (columns) that can be safely visualized to the user. Usually, there is a fixed size area dedicated to histogram visualisation, and there is no point in returning a histogram with a number of buckets (columns) that wouldn't be possible to render. For example - if there is a 200px width size for the histogram, and we want to dedicate 10px for one column, it's wise to ask for, at most, 20 buckets.
Additionally, it accepts one or more String arguments as a second, third (and so on) argument, specifying the filterable attribute name for which histograms should be computed. Attribute must be of a numeric type in order to compute histogram data.
Each attribute is represented by a separate Histogram data structure indexed by its attribute name.

Example usage:

The query results in a response with two histogram data structures computed for the value of its attributes, width and height.

Price histogram

The priceHistogram requirement constraint usage triggers the computation and adding of an object of the type, allowing you to render histograms to the query response.
In the first int argument, it expects the number of the histogram buckets (columns) that can be safely visualized to the user. Usually, there is fixed size area dedicated to the histogram visualisation, and there is no point in returning a histogram with a number of buckets (columns) that wouldn't be possible to render. For example - if there is a 200px width size for the histogram, and we want to dedicate 10px for one column, it's wise to ask for, at most, 20 buckets.
The result will be represented with a single Histogram data structure in the response, containing the statistics on the price layout in the query result.

Example usage:

Hierarchy statistics

The hierarchyStatistics require constraint triggers the computation of the statistics for the referenced hierarchical entities, and adds an object of the type to the query response. The hierarchy statistics requirement helps to render the sensible category menus along with an insight about the number of the entities within them.
It has at least one String argument that specifies the reference name targeting a hierarchical entity. Additional arguments allow for the passing of requirements for fetching the referenced entity contents, so that the number of queries to evitaDB is minimized, and all the data is fetched in single query.
The data structure is organized in the tree structure, reflecting the hierarchy of the entities of the specified reference name that are referenced by entities returned by the primary query. For each node in the tree (one hierarchical entity), there is a number that represents the count of currently queried entities relating to that referenced hierarchical entity node (either directly or to some subordinate entity of this hierarchical entity) and matching the query filter.

Example usage:

This require constraint is usually used when hierarchical menu rendering is needed. For example, when we need to render a menu for the entire e-commerce site, but we want to take excluded subtrees into an account, and also reflect the filtering conditions that may filter out dozens of products (and thus leading to empty categories), we can invoke following query:

This query would return first page with 20 products (omitting hundreds of others on additional pages), but also returns a data structure in a different part of the response. This object can contain following structure:
The tree will contain the CATEGORY entities fetched with their attributes instead their names. You see this reflected in the example. The number next to the arrow represents the count of the products that are referencing this category (either directly or some of its children - therefore, the nodes higher in the tree always have a bigger or equal count than the sum of counts of their child nodes). You can see, there are only categories valid for the passed query - the excluded category subtree will not be a part of the category listing (the query filters out all the products with the excluded category tree) and there is no category that happens to be empty (e.g. contains no products or only products that don't match the filter constraint).

Author: Ing. Jan Novotný

Date updated: 15.12.2022

Documentation Source