Search query language

Syntax description of the search query language.

This page lists the query expressions and the operators, Composable Commerce Search APIs have in common. Find the resource-specific elements of the query language, like searchable fields, on the respective API reference page:

A search request submitted as payload on a Search API is a JSON object that contains the following fields:

  • query - SearchQuery - Required
    A simple expression or compound expression.
  • sort - Array of SearchSorting - Optional
    The parameters for sorting search results.
  • limit - Number - Optional
    The limit parameter for pagination.
  • offset - Number - Optional
    The offset parameter for pagination.

Example:

The following example search request returns all resources matching the English name (name.en) "laptop stand" sorted by name in descending (desc) order. The result is limited to the first 20 resources matching the query.
{
  "query": {
    "exact": {
      "field": "name",
      "language": "en",
      "value": "laptop stand"
    }
  },
  "sort": [
    {
      "field": "name",
      "language": "en",
      "order": "desc"
    }
  ],
  "limit": 20,
  "offset": 0
}

SearchQuery

A SearchQuery is a JSON object assigned as value to a query field on root level of a search request's payload: The object contains either:
One SearchQuery can contain up to 50 simple or compound expressions.
String-type values in simple expressions are limited to 256 characters. Exceeding this limit returns an invalid input error.

Example:

The following example SearchQuery demonstrates how to search for all Products which have banana in their English name (name.en), and a Product Variant with the text Attribute someattribute that has a value equal to 12:
{
  "query": {
    "and": [
      {
        "fullText": {
          "field": "name",
          "language": "en",
          "value": "banana"
        }
      },
      {
        "filter": [
          {
            "exact": {
              "field": "variants.attributes.someattribute",
              "fieldType": "text",
              "value": "12"
            }
          }
        ]
      }
    ]
  }
}

Simple expressions

Simple expressions specify a search query for a single searchable field. The query language provides different query expressions supporting specific use cases, embed one of the following expression types into the SearchQuery as field specified by the field name:
Expression typeField nameExample use case
existsexistsChecks whether a specified field has a non-null value.
exactexactPerforms exact match on values of a specified field.
prefixprefixSearches for values starting with a specified prefix.
rangerangeSearches for values within a specified range.
wildcardwildcardSearches for values with specified wildcards.
fullTextfullTextPerforms full-text search on a specified field.
fuzzy BETAfuzzySearches for values with minor spelling variations.

exists

An exists query matches resources that have a field with a non-null value.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided when field is a non-standard field on a resource, like a Product Attribute.
    For Order Search, you must provide customType: String - CustomType instead if field is a Custom Field.
The following exists query matches Products that have a value for the Attribute someattribute:
{
  "query": {
    "exists": {
      "field": "variants.attributes.someattribute"
    }
  }
}

exact

Searches for exact matches of the provided search term with or without taking casing into account. With this expression, the search term yellow car, for example, returns resources with values yellow car or Yellow Car, but not with car or best yellow car since those values match only partially, but not exactly. If you want partial matches on several search terms to apply, consider using a fulltext expression instead. A prefix expression is suitable when yellow car should match yellow cars also.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided if field is a non-standard field on a resource, like a Product Attribute.
    For Order Search, you must provide customType: String - CustomType instead if field is a Custom Field.
  • language: Locale - Language of the localized value. Must be provided when field is of type localizedTextField. The provided Locale must be one of the languages of your Project. Otherwise, the search request does not return any result.
  • value: String - Search term the value of the specified field must match. If the search term contains several words separated by whitespaces, the value must match to the field value as a whole. With the additional caseInsensitive parameter you can control whether casing should be considered or ignored.
  • values BETA: Array of String - List of search terms. At least one of the terms must match the specified field term (term_1 OR term_2 OR ... OR term_100). The maximum number of values per exact expression is 100. The maximum total number of values over all exact expression is 500.
    Either value or values must be provided. values must not be empty.

Optional fields:

  • caseInsensitive: Boolean
    • true: Returns resources for which the provided search term matches exactly or differs in casing only.
    • false (default): Returns only those resources for which the provided search term matches exactly including casing.
The following exact query searches for resources with the key = KEY101. This query also returns resources that have the lowercased version of the value (key101) since the caseInsensitiveparameter is set totrue.
{
  "query": {
    "exact": {
      "field": "key",
      "value": "KEY101",
      "caseInsensitive": true
    }
  }
}
The following example query searches for multiple resources, that have a key of KEY101, KEY102, or KEY201. Specify multiple search terms for the same field with the values field instead of the value field.
{
  "query": {
    "exact": {
      "field": "key",
      "values": ["KEY101", "KEY102", "KEY201"],
      "caseInsensitive": true
    }
  }
}

prefix

Searches for values that start with a specified prefix.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided when field is a non-standard field on a resource, like a Product Attribute.
    For Order Search, you must provide customType: String - CustomType instead if field is a Custom Field.
  • language: Locale - Language of the localized value. Must be provided when field is of type localizedTextField. The provided Locale must be one of the languages of your Project. Otherwise, the search request does not return any result.
  • value: String - The search term the values of the specified field must match. You can provide several terms separated by whitespaces.

Optional fields:

  • caseInsensitive: Boolean
    • true: Returns resources for which the provided search term matches exactly or differs in casing only.
    • false (default): Returns only those resources for which the provided search term matches exactly including casing.

Example:

The following prefix query matches resources with names including card, carton, caravan, or carpet.
{
  "query": {
    "prefix": {
      "field": "name",
      "language": "en",
      "value": "car"
    }
  }
}
Searching for yell ca will not match the value yellow car as all terms form one prefix. You would need to search for yellow c to match yellow car instead.

range

Searches for values between specified boundaries to restrict the search query to certain time frames or ranges of numerical values.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided when field is a non-standard field on a resource, like a Product Attribute.
    For Order Search, you must provide customType: String - CustomType instead if field is a Custom Field.

The range must contain either an upper or a lower boundary. Hence you must provide at least one of the operators below as key for the JSON property.

OperatorSymbolBehavior
gt>Only matches values strictly greater than the specified value.
lt<Only match values strictly lesser than the specified value.
gte>=Only matches values greater than or equal to the specified value.
lte<=Only matches values lesser than or equal to the specified value.
In the property value you specify the lower or upper boundary for the field to search for. The data type of the specified value must match the data type of the searchable field.

Optional fields:

By providing only one of the above operators, you specify an open range for the value to search for. You optionally close the range with a corresponding boundary when you provide a second operator with a value.

Example:

You want to find resources that were last modified on the 25 August 2018. For this, you specify the field to search for as lastModifiedAt and determine its data type as DateTime. Since the dates you are looking for are in the past, you can limit your search request to everything that happened between the least possible DateTime on that very day (gte as lower boundary) and the least possible DateTime on the following day (lt as upper boundary), like so:
{
  "query": {
    "range": {
      "field": "lastModifiedAt",
      "gte": "2018-08-25T12:00:00.000Z",
      "lt": "2018-08-26T12:00:00.000Z"
    }
  }
}

wildcard

With a wildcard expression you can use placeholders in values that specify which part of the value does not need to match the search term exactly. Such expression is suitable when your query should tolerate slight variations in spellings for search terms, like whisky and whiskey. With a wildcard expression, you don't need two exact expressions for both terms separately, but only one.
wildcard expressions are not as efficient as other expressions and should only be used when no other expression is applicable for your use case. For example, when the search term starts with a static string followed by a wildcard, a prefix expression is sufficient and should be applied instead.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided when field is a non-standard field on a resource, like a Product Attribute.
    For Order Search, you must provide customType: String - CustomType instead if field is a Custom Field.
  • language: Locale - Language of the localized value. Must be provided when field is of type localizedTextField. The provided Locale must be one of the languages of your Project. Otherwise, the search request does not return any result.
  • value: String - Search term the value of the specified field must match. Use following characters as placeholders:
    • * for zero, one, or more characters
    • ? for exactly one character.
    With the additional caseInsensitive parameter you can control whether casing should be considered or ignored.

Optional fields:

  • caseInsensitive: Boolean
    • true: Returns resources for which the provided search term matches exactly or differs in casing only.
    • false (default): Returns only those resources for which the provided search term matches exactly including casing.
The following example query returns results for names written as whisky as well as whiskey.
{
  "query": {
    "wildcard": {
      "field": "name",
      "language": "en",
      "value": "whisk*y",
      "caseInsensitive": true
    }
  }
}
The following example is similar to the example query for prefix, but this time we are searching for names starting with car, but having exactly one additional character, not more. With a prefix query you cannot restrict the characters followed by the prefix term, but in a wildcard query you can use the ? character to specify that exactly one character must follow the prefix to match the query:
{
  "query": {
    "wildcard": {
      "field": "name",
      "language": "en",
      "value": "car?",
      "caseInsensitive": true
    }
  }
}
Multiple wildcards can also be used. The following wildcard query matches resources with names including career, corner, cursor, and corr.
{
  "query": {
    "wildcard": {
      "field": "name",
      "language": "en",
      "value": "c?r*r",
      "caseInsensitive": true
    }
  }
}

fullText

Performs a full text search on the specified field.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided when field is a non-standard field on a resource, like a Product Attribute.
    For Order Search, you must provide customType: String - CustomType instead if field is a Custom Field.
  • language: Locale - Language of the localized value. Must be provided when field is of type localizedTextField. The provided Locale must be one of the languages of your Project. Otherwise, the search request does not return any result.
  • value: String - The search term the values of the specified field must match. You can provide several terms separated by whitespaces. With the additional mustMatch parameter you can control whether all of the provided terms must match or any of those.

Optional fields:

  • mustMatch: String
    • any: Returns resources for which at least one of the provided search terms match.
    • all (default): Returns only those resources for which all the provided search terms match.

Examples:

If you search for yellow car without the mustMatch parameter, the search result contains resources for which the English name is exactly yellow car:
{
  "query": {
    "fullText": {
      "field": "name",
      "language": "en",
      "value": "yellow car"
    }
  }
}
If you want to search for resources that have either yellow or car in their English name, add the mustMatch parameter to the full text query and set it to any:
{
  "query": {
    "fullText": {
      "field": "name",
      "language": "en",
      "value": "yellow car",
      "mustMatch": "any"
    }
  }
}
Note that all the provided search terms must match exactly in fullText search expressions. If you need partial matches, consider prefix search instead.

fuzzy BETA

A fuzzy search expression matches resources that contain terms similar to the search term, allowing for slight variations such as typos or minor character differences. This is useful when you want to find results even if the user makes small spelling mistakes.

The API automatically adjusts the effective fuzziness level based on the length of the search term to maintain relevance and to prevent excessively broad matches for short search terms. As a result, clients do not need to manually validate or constrain the level based on term length.

fuzzy expressions are not as efficient as other expressions and should only be used when no other expression is applicable for your use case. In most cases, a fullText or an exact expression is sufficient for handling common search requirements.
Usage guidelines for fullText and fuzzy search:
  • Use fullText search for longer text fields, such as product descriptions or detailed content, where users are likely to enter multiple words or phrases.
  • Apply fuzzy search primarily to short fields that users type directly, such as product names, SKUs, or attributes like color. Fuzzy search helps account for typos or minor spelling mistakes.
  • We suggest limiting the use of fuzzy expressions to 10 per query to maintain good performance and relevance.
  • Avoid using fuzzy search indiscriminately across all fields, as it can negatively impact performance and may return less relevant results.
  • Combine fullText and fuzzy in queries when you want to balance precision and tolerance for user input errors. For example, use an OR expression to search both the exact term (with fullText and a boost) and a fuzzy match for user-entered fields:
{
  "query": {
    "or": [
      {
        "fullText": {
          "field": "name",
          "language": "en",
          "value": "shoes",
          "boost": 3
        }
      },

      {
        "fuzzy": {
          "field": "name",
          "language": "en",
          "value": "shoes",
          "level": 1
        }
      }
    ]
  }
}
  • It can be helpful in cases where users might enter free text fields (e.g.: search bar in storefront applications). For example, imagine users searching for "Red Shoes": you can craft a query that searches the product name with fuzzy (e.g.: "Shoes") and the color attribute with fuzzy (e.g.: "red"), using mustMatch: "any" to combine the expressions for each field, e.g.:
{
  "query": {
    "and": [
      {
        "fuzzy": {
          "field": "name",
          "language": "en",
          "value": "red shoes",
          "level": 1,
          "mustMatch": "any"
        }
      },
      {
        "fuzzy": {
          "field": "variants.attributes.color",
          "fieldType": "text",
          "value": "red shoes",
          "level": 1,
          "mustMatch": "any"
        }
      }
    ]
  }
}

Anti-patterns:

  • Do not use fuzzy on long text fields, as it can lead to irrelevant matches and performance issues.
  • Avoid combining multiple fuzzy expressions without clear intent, as this can degrade both relevance and speed.
In summary, use fullText for comprehensive text matching, and apply fuzzy selectively to user-input fields to improve search experience without sacrificing performance.

Required fields:

  • field: String - Searchable field.
  • fieldType : String - SearchFieldType. Must be provided when field is a non-standard field on a resource, like a Product Attribute.
  • language: Locale - Language of the localized value. Must be provided when field is of type localizedTextField. The provided Locale must be one of the languages of your Project. Otherwise, the search request does not return any result.
  • value: String - The search term you want to find fuzzy matches for.
  • level: Number - The maximum fuzziness level desired for the search term provided with the value. Allowed values are 0, 1, and 2, but the API will adjust the fuzziness level per search term if it exceeds the maximum allowed for the given string length according to the following rules:
    • Terms with 1–2 characters: 0 (exact match).
    • Terms with 3–5 characters: 1 (up to one difference is allowed).
    • Terms with more than 5 characters: 2 (up to two differences are allowed).

    Example:

    If you search for the term "shert" (5 characters) and set level to 2, the system will automatically adjust the level to 1, which is the maximum allowed for a 5-character string. The search will then match terms with only one substitution, for example, "shirt."
    Fuzziness level higher than allowed is automatically adjusted to maximumjson
    {
      "query": {
        "fuzzy": {
          "field": "name",
          "language": "en",
          "value": "shert", // 5 characters
          "level": 2 // --> 1
        }
      }
    }
    

Optional fields:

  • mustMatch: String - Controls whether all of the provided terms must match or any of those.
    • all (default): Returns only those resources for which all the provided search terms match.
    • any: Returns resources for which at least one of the provided search terms match.
If value contains multiple search terms, the fuzziness level is applied to each term individually.

Example:

Consider the following query, which searches for products with a name similar to grean handbg with a desired fuzziness level of 2. The API will adjust the fuzziness level for grean to 1 because that is the maximum level for terms with a length of 5 characters. The fuzziness level for handbg stays at 2 because the term has more than 5 characters. The query will return Products for which green handbag matches successfully.
Example query with fuzziness level of 2 for multiple search termsjson
{
  "query": {
    "fuzzy": {
      "field": "name",
      "language": "en",
      "value": "grean handbg",
      "level": 2,
      "mustMatch": "all"
    }
  }
}
The fuzziness level defines the maximum allowable Damerau-Levenshtein distance between the search term and the results. It is the number of single-character edits (insertions, deletions, or substitutions) required to change one word into the other.

Compound expressions

The outermost layer of the query is a compound expression. This expression specifies how the composition of the sub-expressions is evaluated. Sub-expressions can be simple expressions or compound expressions.

The following compound expressions are currently supported:

ExpressionBehavior
andonly matches resources that match all sub-expressions.
oronly matches resources where at least one of the sub-expressions is matched.
If you want to search for multiple OR-combined values for the same field, you can specify them in the values of an exact simple expression instead. This reduces the number of expressions that count toward the 50 expressions limit in a query.
notonly matches resources that do not match any of its sub-expressions.
filterMatching resources of a query are checked for their relevancy to the search. The relevancy is expressed by an internal score. All expressions except filter expressions contribute to that score. All sub-expressions of a filter are implicitly connected with an and expression.
The following example shows an and compound expression query to find the price of EUR 22.22 across Product Variants. In addition, we want to search for specific countries (Austria, Belgium, Croatia) for which the price is specified. Therefore, the query consists of three exact expressions; one for the currencyCode field, one for the centAmount field, and one for the country field of the variants.prices:
{
  "query": {
    "and": [
      {
        "exact": {
          "field": "variants.prices.currencyCode",
          "value": "EUR"
        }
      },
      {
        "exact": {
          "field": "variants.prices.centAmount",
          "value": 2222
        }
      },
      {
        "exact": {
          "field": "variants.prices.country",
          "values": ["AT", "BE", "HR"]
        }
      }
    ]
  }
}
The last exact expression contains the values field, which lists multiple values for the country. This means, the query will match if any of these values match.

Searchable fields

Each simple expression contains a field property to specify which field of a resource should be searched through. The API matches the search term only against the values of the specified field, not against any field of a resource. If you want to search through several fields of a resource, you need to formulate simple expressions for each of those fields.

Find the searchable fields specific to the resource on the respective Search API documentation:

SearchFieldType

Possible values for the fieldType property on simple expressions indicating the data type of the field.
boolean
For Boolean fields, AttributeBooleanType Attributes, and BooleanType Custom Fields.
text
For string fields, AttributeTextType Attributes, and StringType Custom Fields.
ltext
For LocalizedString fields, AttributeLocalizableTextType Attributes, and LocalizedStringType Custom Fields.
enum
For enum fields, AttributeEnumType Attributes, and EnumType Custom Fields.
lenum
For localized enum fields, AttributeLocalizedEnumType Attributes, and LocalizedEnumType Custom Fields.
number
For number fields, AttributeNumberType Attributes, and NumberType Custom Fields.
money
For Money fields and AttributeMoneyType Attributes.
date
For Date fields, AttributeDateType Attributes, and DateType Custom Fields.
datetime
For DateTime fields, AttributeDateTimeType Attributes, and DateTimeType Custom Fields.
time
For Time fields, AttributeTimeType Attributes, and TimeType Custom Fields.
reference
For Reference fields and AttributeReferenceType Attributes.
set_boolean
For Set of Boolean fields, AttributeSetType of boolean Attributes, and SetType of boolean Custom Fields.
set_text
For Set of string fields, AttributeSetType of text Attributes, and SetType of text Custom Fields.
set_ltext
For Set of LocalizedString fields, AttributeSetType of ltext Attributes, and SetType of ltext Custom Fields.
set_enum
For Set of enum fields, AttributeSetType of enum Attributes, and SetType of enum Custom Fields.
set_lenum
For Set of localized enum fields, AttributeSetType of lenum Attributes, and SetType of lenum Custom Fields.
set_number
For Set of number fields, AttributeSetType of number Attributes, and SetType of number Custom Fields.
set_money
For Set of Money fields and AttributeSetType of money Attributes.
set_date
For Set of Date fields, AttributeSetType of date Attributes, and SetType of date Custom Fields.
set_datetime
For Set of DateTime fields, AttributeSetType of datetime Attributes, and SetType of datetime Custom Fields.
set_time
For Set of Time fields, AttributeSetType of time Attributes, and SetType of time Custom Fields.
set_reference
For Set of Reference fields and AttributeSetType of reference Attributes.

Types of fields

For standard fields on indexed resources, the Search APIs classify the following types of fields:

  • boolean: for boolean fields.
  • long: for integer number fields.
  • double: for floating point number fields.
  • date: for Date fields.
  • dateTime: for DateTime fields.
  • keyword: for fields holding unique identifiers.
  • text: for string fields.
  • localizedText: for LocalizedString fields.
  • phone: for phone numbers containing non-numerical characters for formatting.

Simple expression supported for which type of field

A checkmark indicates which simple expression you can use for which type of field.
TypesfullTextexactprefixrangewildcardfuzzyexists
boolean✓✓
long, double, date, dateTime✓✓✓
keyword✓✓✓✓✓
text and localizedText✓✓✓✓✓✓
phone✓✓✓✓

Boost query results

If you include multiple simple expressions, the optional boost field is a way to make the results that match one particular query more relevant than results that match the others. A boost value between 0 and 1 lowers the relevance, values greater than 1 give the simple expression a higher relevance.
The following query demonstrates how to make results with "butter" in the name score more relevant than those with "butter" in the description.
{
  "query": {
    "or": [
      {
        "fullText": {
          "field": "name",
          "language": "en",
          "value": "butter",
          "boost": 2
        }
      },
      {
        "fullText": {
          "field": "description",
          "language": "en",
          "value": "butter"
        }
      }
    ]
  }
}

SearchSorting

Sorting parameters provided with a Search request.

field​
String​
Use any searchable field of the resource as sort criterion, or "score" to sort by relevance score calculated by the API.
language​
Locale​
order​
Specify the order in which the search results should be sorted. Can be asc for ascending, or desc for descending order.
mode​
Specify the sort mode to be applied for a set-type field.
fieldType​
Provide the data type of the given field.
filter​
SearchQuery​
Allows you to apply a sort filter.
The following example sorts the results ascending by createdAt:
{
  "sort": [
    {
      "field": "createdAt",
      "order": "asc"
    }
  ]
}

Sort order

asc

Ascending sort order, the lowest value is listed first.

desc

Descending sort order, the highest value listed first.

Sort mode

If you sort by a field in an array (like variants.prices.centAmount) you can optionally pass a sort mode. This is relevant because a single Product can have multiple variants and thus multiple centAmount fields. That means that there might not be a single value to sort on, but multiple. Using the sort mode we can choose which of the values in the array to use for sorting or how to aggregate them. The default sorting mode is min

Following four sort modes are provided:

  • min - Use the minimum of all available values
  • max - Use the maximum of all available values
  • avg - Use the average of all available values
  • sum - Use the sum of all available values.

If a Product is missing that field, it will be at the last position.

The following example uses min sort mode to sort by variants.prices.centAmount in descending order:
{
  "sort": [
    {
      "field": "variants.prices.centAmount",
      "language": "en",
      "order": "desc",
      "mode": "min"
    }
  ]
}

Sort filter

If sort modes are not enough to specify exactly which resources or aggregation you want to sort on, use a sort filter.
The following example uses a filter to prioritize Products in the Category whose id is 4054a159-7f3e-4fe9-a30c-8db80ca7d665.
{
  "sort": [
    {
      "field": "name",
      "language": "en",
      "order": "asc",
      "filter": {
        "exact": {
          "field": "categories",
          "value": "4054a159-7f3e-4fe9-a30c-8db80ca7d665"
        }
      }
    }
  ]
}
Compound expressions can be used to express complex sorting conditions. The following example uses a filter to sort on prices scoped to Channel whose id is fb16244b-3963-4b9e-9cb0-69a1f563a854 and to currency EUR.
{
  "sort": [
    {
      "field": "variants.prices.centAmount",
      "filter": {
        "and": [
          {
            "exact": {
              "field": "variants.prices.channel",
              "value": "fb16244b-3963-4b9e-9cb0-69a1f563a854"
            }
          },
          {
            "exact": {
              "field": "variants.prices.currencyCode",
              "value": "EUR"
            }
          }
        ]
      },
      "order": "asc"
    }
  ]
}
Results that do not match the filter condition will be positioned at the tail of the result with an undefined order. It's advisable to only use sort filters for criteria that are already present in the query or postFilter, thus guaranteeing a matching sort value is found.
In case this is not feasible, subsequent sort definitions may be used to define the order of products that did not match the previous sort filters.

Pagination

A response to the search request contains the first 20 results by default. Pagination allows you to retrieve the first 10 000 results by requesting them page by page. The total field in a query result indicates how many results match the search query in total.

Limit

With the limit parameter you can set the maximum number of results returned on a page. Any value between 1 and 100 is allowed, the default limit is 20.

Offset

The offset parameter controls the starting point for retrieving paginated results. With the default value 0 you retrieve the first page of query results. Setting "offset" : 1 skips the first page and returns the second page of results, and so on. Each page contains a number of results defined by the limit parameter.
The maximum allowed offset is 9900. When combined with the maximum limit of 100, this allows you to retrieve the first 10 000 results in total.
Setting pagination parameters exceeding this limit will result in an InvalidInput error with the message "Pagination cannot be used to fetch more than the first 10000 results."