# Discount Predicates Certain resources have a `predicate` or `cartPredicate` field. In particular, [Product Discounts](https://docs.commercetools.com/api/projects/productDiscounts.md), [Cart Discounts](https://docs.commercetools.com/api/projects/cartDiscounts.md), and [Shipping Method](https://docs.commercetools.com/api/projects/shippingMethods.md) 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 the identifiers that you can use to create predicates, see [Discount Predicate Identifiers](https://docs.commercetools.com/api/projects/predicates.md). 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](https://docs.commercetools.com/api/predicates/query.md). ## Predicate syntax Predicates consist of three elements: - [Predicate Field Identifiers](https://docs.commercetools.com/api/projects/predicates.md), which are specific to [Product Discounts](https://docs.commercetools.com/api/projects/productDiscounts.md), [Cart Discounts](https://docs.commercetools.com/api/projects/cartDiscounts.md), and [Shipping Methods](https://docs.commercetools.com/api/projects/shippingMethods.md). - Operators, which create logical comparisons between values. - Values, which are data – either simple values like `1`, `"Hello"`, or `true` or collections of values like `("xl", "xxl")` – to compare with a predicate field identifier. For example, take the following ProductDiscount predicate: ``` sku = "AB-123" ``` - The predicate field identifier for the Product Variant 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](https://docs.commercetools.com/api/errors.md#400-bad-request). One exception to this rule is [comparison operators](https://docs.commercetools.com/api/predicates/predicate-operators.md#comparison-operators), however. ## Operators ### Equality operators Equality operators compare a field identifier with a value. (a CSV formatted table follows. The first line are the column names.) Operator,Description `=`,Checks if the field identifier's value equals the comparison value. `!=` or `<>`,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](https://docs.commercetools.com/api/predicates/predicate-operators.md#containment-operators) to compare collections. ### Comparison operators Comparison operators compare the value of two numbers or number-like fields. You can use comparison operators on the following predicate identifiers: - Any [ProductDiscount predicates](https://docs.commercetools.com/api/projects/predicates.md#productdiscount-predicates) or [Cart Predicate Function](https://docs.commercetools.com/api/projects/predicates.md#cart-predicate-functions). - Any [Attribute](https://docs.commercetools.com/urn?urn=ctp%3Aapi%3Atype%3AAttribute) or [CustomField](https://docs.commercetools.com/api/projects/predicates.md#customfield-field-identifiers) with a numerical value of Number, Money, or DateTime. - Custom [Type](https://docs.commercetools.com/urn?urn=ctp%3Aapi%3Atype%3AType) IDs and keys (Predicate identifiers: `custom.type.id`, `custom.type.key`). - SKUs (Predicate identifier: `sku`). - Slugs (Predicate identifier: `slug`). You can only use comparison operators when comparing a single value to a single value. (a CSV formatted table follows. The first line are the column names.) 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 or does not contain one or more specified values. You can only use containment operators on fields holding a collection of values, like arrays and sets: - `categories.id` - `categoriesWithAncestors.id` - Any [Attribute](https://docs.commercetools.com/urn?urn=ctp%3Aapi%3Atype%3AAttribute) or [CustomField](https://docs.commercetools.com/api/projects/predicates.md#customfield-field-identifiers) with a `Set` type. (a CSV formatted table follows. The first line are the column names.) Operator,Description `contains`,Checks if a field identifier contains a value. `contains any`,Checks if a field identifier contains any of the value(s) in a set. `contains all`,Checks if a field identifier contains all of the value(s) in a set. `in`,Checks if a field identifier's value(s) is contained in an array. `not in`,Checks if a field identifier's value(s) is not contained in an array. Example: ```javascript attributes.season contains "spring2019" ``` - The field identifier is `attributes.season`. - The operator is `contains`. - The values to check are `"spring2019"`. This example evaluates as true if `spring2019` is contained in a product's `season` attribute. For this request to succeed, `season` must be a `Set` type. ```javascript 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` type. ```javascript 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. For this request to succeed, `season` must be a `Set` type. Example: ``` attributes.size in ("xxl", "xl") ``` - The field identifier is `attributes.size`. - The operator is `in`. - The values to compare are `"xxl"` and `"xl"`. This example evaluates as true if either `xxl` or `xl` are contained in a product's `size` enum attribute. ### 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](https://docs.commercetools.com/urn?urn=ctp%3Aapi%3Atype%3AAttribute) or [CustomField](https://docs.commercetools.com/api/projects/predicates.md#customfield-field-identifiers) with a `Set` type. (a CSV formatted table follows. The first line are the column names.) 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: ```javascript 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 when creating a new product. This statement evaluates as true if no product channel is set. ```javascript 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. ```javascript 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. ### Combine and nest operators You can combine operators to create more complex or nested conditional predicates. (a CSV formatted table follows. The first line are the column names.) 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: ```javascript 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: ```javascript 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. ### Use 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: ```javascript 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. ## Related pages - [Section overview page](https://docs.commercetools.com/api.md) - [Previous page: Discount Groups](https://docs.commercetools.com/api/projects/discount-groups.md) - [Next page: Discount Predicate field identifiers](https://docs.commercetools.com/api/projects/predicates.md)