Discount Predicates
Some resources in the commercetools API have a predicate
or cartPredicate
field. In particular, Product Discounts, Cart Discounts, and Shipping Method have predicate fields. This field expects a conditional statement known as a predicate. When a predicate evaluates as true, the API applies the discount or selects a shipping method.
Predicates consist of field identifiers and operators. For more information on creating predicates, see Discount Predicate Identifiers.
You cannot use the syntax described here to construct API queries using the where
field. General-purpose queries use a different syntax. For more information, see Query Predicates.
Predicate syntax
Predicates consist of three elements:
- Predicate Field Identifiers, which target specific fields and characteristics of Carts and Products.
- Operators, which create logical comparisons between values.
- Values, which are data – either simple values like
1
,"Hello"
, ortrue
or collections of values like("xl", "xxl")
– to compare with a predicate field identifier.
For example, take the following predicate:
sku = 'AB-123';
- The predicate field identifier is
sku
. - The operator is
=
. - The value is
"AB-123"
.
Operators always evaluate contextually aware values before comparing or evaluating the predicate. The API ensures that the values of the field identifiers are compatible with the values provided. For example, Strings will only evaluate against Strings. Constructing a predicate that compares different data types – String and Number, for example – returns a 400 Bad Request. One exception to this rule is comparison operators, however.
Operators
Equality operators
Equality operators compare a field identifier with a value.
Operator | Description |
---|---|
= | Checks if the field identifier's value equals the comparison value. |
!= , <> | Checks if the field identifier's value is not equal to the comparison value. |
Example:
product.key = 'holidayTShirt';
- The predicate field identifier is
product.key
. - The operator is
=
. - The value is
"holidayTShirt"
.
Example:
custom.season = ('spring2019', 'summer2019');
- The field identifier is
custom.season
. - The operator is
=
. - The values to compare are
"spring2019"
and"summer2019"
.
When using the =
when comparing collections, =
only returns true for exact matches: both "spring2019"
and "summer2019"
must be present in custom.season
, and no other values. In most cases, we recommend using a containment operator to compare collections.
Comparison operators
Comparison operators compare the value of two numbers or number-like fields. You can only use comparison operators for fields that have the following data types:
- Number
- Money
- DateTime
- Date
- Time
You can also use comparison operators on the following predicate identifiers:
- Any Cart Predicate Function.
- Any Attribute or CustomField with a numerical value of Number, DateTime, Date, or Time.
- CustomType IDs and Keys (Predicate identifiers:
custom.type.id
,custom.type.key
). - SKU (Predicate identifier:
sku
). - Slugs (Predicate identifier:
slug
).
You can only use comparison operators when comparing a single value to a single value.
Operator | Description |
---|---|
> | Checks if the field identifier's value is numerically greater than the comparison value. |
>= | Checks if the field identifier's value is numerically greater than or equal to the comparison value. |
< | Checks if the field identifier's value is numerically less than the comparison value. |
<= | Checks if the field identifier's value is numerically less than or equal to the comparison value. |
Containment operators
Containment operators check if a collection contains a single value. You can only use containment operators on field identifiers with an Array or Set data type:
categories.id
categoriesWithAncestors.id
- Any Attribute or CustomField with a
Set
type.
Operator | Description |
---|---|
contains , contains any | Checks if a collection contains at least one of the specified values. |
contains all | Checks if a collection contains all values listed. |
in | Checks if a field identifier's value is contained in a collection. |
Example:
attributes.season contains any ("spring2019", "summer2019")
- The field identifier is
attributes.season
. - The operator is
contains any
. - The values to check are
"spring2019"
and"summer2019"
.
This example evaluates as true if either spring2019
or summer2019
are contained in a product's season
attribute. For this request to succeed, season
must be a Set.
attributes.season contains all ("spring2019", "summer2019")
- The field identifier is
attributes.season
. - The operator is
contains all
. - The values to check are
"spring2019"
and"summer2019"
.
This example evaluates as true if both spring2019
and summer2019
are contained in a product's season
attribute. If only one is present, this example evaluates as false.
Example:
attributes.size in ('xxl', 'xl');
- The field identifier is
attributes.size
. - The operator is
in
. - The values to compare are
"xxl"
and"xl"
.
Defined and empty operators
Defined and empty operators check whether a field or collection has a value. Defined and empty operators are only used on optional fields on a resource.
You can use the is defined
and is not defined
operators with any single value field.
You can only use the is empty
and is not empty
fields with collections:
categories.id
categoriesWithAncestors.id
- Any Attribute or CustomField with a
Set
type.
Operator | Description |
---|---|
is defined | Checks if a field identifier exists on a resource and contains a value. |
is not defined | Checks if a field identifier does not exist on a resource. |
is empty | Checks if a collection does not contain values. |
is not empty | Checks if a collection contains values. Does not check on the content of the values themselves. |
Examples:
channel.id is not defined
- The field identifier is
channel.id
. - The operator is
is not defined
. - No value is explicitly provided in this predicate, the value, in this case, is implicitly
true
.
In this example, defining a Product's channel is not required by commercetools when creating a new product. This statement evaluates as true if no product channel is set.
country is defined
- The field identifier is
country
. - The operator is
is defined
. - No value is explicitly provided in this predicate, the value, in this case, is implicitly
true
.
In this example, once again, a Cart does not need to have a country
defined. This statement evaluates as true if a country is in fact set.
attributes.season is empty
- The field identifier is
attributes.season
. - The operator is
is empty
. - No value is explicitly provided in this predicate, the value, in this case, is implicitly
true
.
This example evaluates as true if a Product Type has an season
attribute but it does not have a default value.
Combining and nesting operators
You can combine operators to create more complex or nested conditional predicates.
Syntax | Description |
---|---|
or | A logical disjunction: if the first condition or the second condition is true... |
and | A logical conjunction: if the first condition and the second condition are true... |
not | A logical negation: if the condition is not true.. |
( ) | Nests predicate conditions. |
Examples:
custom.bookingStart = "2016-11-24" and custom.bookingEnd = "2016-12-04"
- The first field identifier is
custom.bookingStart
. - The first operator is
=
. - The first value is
"2016-11-24"
. - The
and
keyword combines the two statements so that both must be true. - The second field identifier is
custom.bookingEnd
. - The second operator is
=
. - The second value is
"2016-12-04"
.
You can also nest parentheses:
not(product.key = "holidayTShirt" and(product.price = "10.00 EUR" or product.price = "20.00 EUR"))
This example only evaluates true if the product.key
is not "holidayTShirt"
, and it does not have a price of 10 or 20 euros.
Using the not
operator
The not
operator, when used in conjunction with any other operator, negates the statement inside of parentheses. This is most useful when using the contains
operators, to check if an item is not inside a given collection.
Example:
not(product.key = "holidayTShirt" or product.id = "456")
The or
keyword ensures that if only one of the equality statements needs to evaluate as true. If product.id
equals 456
, or the product.key
is "holidayTShirt"
outer not
statement will evaluate as false.
Discount predicate specification
You can view the discount predicate specification here. The predicate specification is useful when building language parsers.