Pre-filters is a feature built into GroupBy’s search engine that allows you, at query time, to limit the search space to a subset of records in a collection.

Creating such subsets allow you to form custom catalogs for your customers. Customized subsets of the whole collection could be unique per customer.

It provides you the total control over determining visibility of products based on shopper information and product attributes by using logical operators and boolean functions (AND, OR) that can be crafted and changed from query to query for all your customers.

Query Logic

A query logic is the main part of the language that allows an attribute to be constrained by a particular value, such as person.firstName = "John" or a set of values, such as contractId in ["a1", "b2", "c3"]. A query logic follows the grammar:

<fieldname> <operator> <value>

Field Name

The field name represents the JSON path dot notation to the attribute on the record. For example, person.firstName. This field name has two parts:

  • Field = firstName
  • Nested object = person

Each part of a field name must conform to the following rules:

  • Must only contain alphabetic characters in lower and upper case, digits, underscores or hyphens.
  • Must not begin with a hyphen or a digit.

Good Examples:


Bad Examples:

.firstName //Not a valid JSON path
lastName. //Not a valid JSON path
category.33 //Second part starts with a digit
-Internal.promo //First part starts with a hyphen
hastag# //Contains special character
To Do:

Every field (attribute) in a pre-filter expression needs to be defined as refinable in the upload config file. If the field is not refinable, search result will return an error.

  • You can use nested fields in pre-filters expression only if they are not set to child-record in the upload config file.

  • If an attribute specified in a pre-filter expression does not exist on any record, search results will be empty as no records match that expression.

List of Operators

Here is a list of operators we can support:

Operator Description Boolean Float Integer String List
= Equals Yes Yes Yes Yes No
!= / not = Not equals Yes Yes Yes Yes No
> Greater than No Yes Yes No No
>= Greater than or equal to No Yes Yes No No
< Less than No Yes Yes No No
<= Less than or equal to No Yes Yes No No
in In No Yes Yes Yes Yes
!in / not in Not in No Yes Yes Yes Yes
contains Contains No Yes Yes Yes No
!contains / not contains Not contains No Yes Yes Yes No


Values are static literals and can be of different types as follows:

Boolean: A boolean value is either true or false, case-insensitively. True, true, false, and fALsE are all valid boolean values.

Integer: A whole number. Any leading zeros will be ignored, so 0053 and 53 will have the same effect.

Decimal: A decimal number, also known as a float, contains a whole part and a fractional part, such as 3.14.

String: A string literal is surrounded by double quotes (") and can contain any character except for double quotes. Escaping double quotes is not currently supported; for example, "2.5\" screw" is not a valid string literal. Any space in a string value will not be ignored; in the example (ONLINE_FLAG=\"1 \"), the value will be interpreted as 1, followed by space.

Examples of valid string literals include:

"12 Cans"

List: A list is an ordered set of items surrounded by square brackets ([]) and separated by commas (,). Whitespace is ignored, and items can be integers, decimal numbers, or string literals. However, all items in a list must have the same type.

Good Examples:

[1.5, 3.14, 4.7801]
["Volvo", "BMW", "Ford"]

Bad Example:

[12, "price"]

Chaining Query Logic

Query Logic can be chained together using and or or connectives (that are case insensitive) to build more sophisticated expressions. For example:

metadata.tags contains "healthy" OR calories <= 400 AND containsNuts = false

By default, the leftmost connective takes precedence. Therefore, a record that has the string "healthy" in the array attribute metadata.tags still needs to have the attribute containsNuts set to false to match the expression above.


Parenthesis ( ) can be used to limit the scope of chained query logic, effectively controlling the precedence of connectives in an expression. Therefore, the above expression can be changed to the following to ensure all “healthy” records are eligible regardless of their other attributes:

metadata.tags contains "healthy" OR (calories <= 400 AND containsNuts = false)

All opening parentheses must be closed and they may be nested as required. For example:

        contractId in [12, 56, 34]

Order of Processing

The conditions dictated by a pre-filter, if met, narrows down the records (i.e., products) in a collection. These records are then included in the search space.

Any search refinements or queries will be applied after this subset of records is created.

In a nutshell, expression defined by pre-filters are applied before any other search functionality.

Use Case

Custom Catalogs

Consider a scenario where you want the ability to restrict a shoppers’ visibility into products returned by the search engine based off some condition.

It is rather complex to create and manage multiple business rules for multiple shoppers. Creating separate collections for each such business rule may not be a scalable solution either.

The pre-filters feature can be leveraged for this.

For example, if you want to restrict the visibility of Product Set A only to Customer Set B, you may leverage some information specific to Customer Set B to do so. For instance, their product contracts.

You can present that information as a boolean statement of contract related attributes in your query, in order to limit the results to those that satisfy the logical statement.

Implementing Pre-Filters

Pre-filters are specificed in the request body while sending a request to the Search API.

As a user of the API, you can leverage the Search API to restrict all proceeding queries by an end-user of a Search implementation specifically to products that have:

The Brand equals Adidas and Gender is either Men or Women, and Price is less than the numeric value of 60 or Color equals to Green and Category ID contains 220.

Request Example
curl -d '{
	    "query": "country",
	    "clientKey": "Your client key",
	    "pre-filter":"BRAND = \"Adidas\" and (gender = \"Men\" or gender = \"Women\" ) AND variants.stores.price < 60 or (variants.color = \"Green\") and (categoryId CONTAINS \"220\")" 
	  }' "https://yourCustomerID.groupbycloud.com/api/v1/search"