Queries and the SDKs
Learn how to use Query Predicates with the SDK to query your Composable Commerce resources.
After completing this page, you should be able to:
- Identify compound expressions that correctly match their requirements.
- Identity correct usage of input variables in Query Predicates.
On the following page, you will learn about how to use queries in your API requests to make sure that your response from the Composable Commerce API delivers only the results that you need.
We will learn the concepts in three steps, where we will:
- Construct simple queries following the basic syntax checking the value of one field on the resource.
- Combine multiple simple queries using logical operators.
- Enhance our multiple queries with input variables.
Let’s get into it!
Predicate Syntax Basics
Query Predicates are used in the where
query parameter. Each query endpoint lists its possible query parameters. Let's take a look at the following example for Query Customers:
As mentioned on the previous page, the basic syntax follows this schema:
field operator value
Fields are taken from the resource under inspection, but it’s important to note that not all fields that a resource representation provides can be used in a query. In the docs, the Query Predicates page is a great starting point for learning about which fields can be used in a query. Have a look at the documentation for all possible operators and a long list of examples.
Use the SDKs to make queries
Let’s have a look at how we can use Query Predicates with our SDKs. We will take a simple example to start with: let's try to fetch all customers that live in Berlin.
First, let’s break that statement down: all customers living in Berlin. How can we turn it into a predicate? First, let’s rewrite it in straightforward English; we want to fetch all customers whose Shipping Address has Berlin as its city. Then, in our predicate syntax, this could look something like:
addresses(city = "Berlin")
Now let’s see how we can write that with our TypeScript and Java SDKs:
The query is not limited to a single customer, so we would see a CustomerPagedQueryResponse in the response body. Inside the results fields, we can find the list of all customers that matched the predicate.
Compound expressions
Now imagine a scenario where you have to search for customers from Berlin who are not in a particular Customer Group. You could approach creating a query for this scenario in two ways. You could either fetch this data in two calls (Customers from Berlin, and Customers who are not in the Customer Group) and then go through the results to find the intersecting elements. Or, you could use a compound expression to do the job for you.
Composable Commerce predicate compound expressions have the following syntax:
predicate logical-operator predicate
We can use the following logical operators: and
, or
, and not
with our compound expressions.
It is also possible to combine multiple compound expressions together to make even more complex compound expressions by using parentheses.
Here are a few examples:
- To search for a Customer with first name and last name:
firstName = "Peter" and lastName = “Porter”
- Find customers from either Berlin or Munich:
addresses(city = "Berlin" or city = "Munich")
- Find all the customers from Germany except Berlin:
addresses(country = "DE" and not(city= "Berlin"))
Let's look for a moment at examples related to Products. Have a go yourself at translating the following queries into natural English:
variants(attributes(name="color" and value="red"))
variants(attributes(name="color" and value(en-US="red")))
Both of these queries would achieve the same result: returning all Products that have Product Variants in red. Take a special note however of the use of the localized attribute in the second example.
Now let’s see how to create compound expressions with the SDK. Let’s run a request with a compound expression. Pay particular attention to the lines where the predicate is presented.
The predicate we are using is based on the Composable Commerce sample data that is downloaded with a trial Project. If you are using your own data, then you need to adjust the predicate to match your data set.
Using the SDK you can easily combine multiple queries together. In the following examples, we will cover how this works in the Java and TypeScript SDK. You will see that there are some slight differences in how each SDK allows you to express predicates with multiple conditions.
TypeScript
import { apiRoot } from "../impl/apiClient.js";async function productPredicate() {try {const response = await apiRoot.productProjections().get({queryArgs: {where:'variants(attributes(name = "colorlabel" and value(en-GB = "Black")))',},}).execute();console.log("Summary", JSON.stringify(response.body, null, 2));} catch (error) {console.log(JSON.stringify(error, null, 2));}}productPredicate();
Java
Using the Java SDK we can chain multiple conditions using .withWhere()
and .addWhere()
. This combines the predicates with an and
operator.
This predicate will be converted to this:
variants(attributes(name = "colorlabel" and value(en-GB = "Black")))
logger.info("Products available in Red: " +projectApiRoot.productProjections().get().withWhere("variants(attributes(name = \"color\"))").addWhere("variants(attributes(value(en = \"red\")))").executeBlocking().getBody().getResults().size());
Input Variables
Let’s move on to a different use case. Imagine you want to display the number of customers living in the same city as another customer. The solution here would involve creating a query that is based on the current Customer's city, and then you would need to query for the remaining Customers. The city in this example is a dynamic input.
We can use input variables for dynamic inputs using the following syntax:
field operator :variable&var.variable = value
Input variables are useful when you are creating a Query Predicate that uses a dynamic value supplied only at the time of running the query. For example, getting all Products from a Category where the Category will be selected by the user.
category = :categoryId&var.categoryId = categoryId
You can even use multiple variables to check multiple values. See the following example:
variants(sku in :skus)&var.skus=sku1&var.skus=sku2&var.skus=sku3
This query is intended to retrieve multiple products where any of the variants match one of the SKUs provided in the :skus
variable. Let’s break down this predicate to better understand it:
variants(sku in :skus)
: this part of the query is checking for any Product Variants where thesku
is in the list of SKUs provided by the:skus
variable.&var.skus=sku1&var.skus=sku2&var.skus=sku3
: these are the predicate parameter values that define the:skus
variable. Eachvar.skus
parameter specifies an SKU value to be included in the search.
The query will return products that have any of the specified SKUs (sku1
, sku2
, sku3
) in their Product Variants. It uses the logical in
operator, which matches any Product Variant that has an SKU within the provided list.
Let’s apply this to a short example request and use the SDKs. We are interested in getting a count of Customers in the same city as the current Customer. In our example, we want to get a Customer’s ID for a Customer that has a default Shipping Address and update the variable customerId
.