Filtering
List queries such as products and orders take a filter argument. Its type is named after the list it filters: products takes ProductFilterInput, orders takes OrderFilterInput, and so on. Each filter input has fields of its own, such as isPublished or search. Most filter inputs also have four shared fields: AND, OR, NOT and DISTINCT. A few simpler ones, such as AppFilterInput and PluginFilterInput, do not.
This page shows how those fields combine, so you can build a filter for any condition you can describe. The examples use products, but the rules are the same for every filter input that has the four shared fields.
Combining fields
Every field you set adds a condition, and a result must meet all of them. This query returns products that are published and also visible in listings:
query {
products(first: 20, filter: { isPublished: true, visibleInListings: true }) {
edges {
node {
id
name
}
}
}
}
A field you leave out, or set to null, adds no condition.
AND
The fields of one filter already combine with AND, so you only need AND to use a field a second time. A GraphQL input object cannot name the same field twice, so the second condition goes in a nested filter. This query returns products that match both search terms:
query {
products(first: 20, filter: { search: "jacket", AND: { search: "wool" } }) {
edges {
node {
id
name
}
}
}
}
AND also groups conditions, which matters once you use OR. See Grouping conditions.
OR
OR takes another filter of the same type as an alternative. A result matches when it matches the OR filter, or when it matches every other condition set beside it. This filter returns products that are unpublished, or have warnings, or both:
filter: { isPublished: false, OR: { hasWarnings: true } }
OR is the alternative to all of the other conditions beside it together, AND and NOT included. This filter:
filter: { isPublished: true, visibleInListings: true, OR: { hasWarnings: true } }
means (published and visible in listings) or has warnings. It does not mean published and (visible in listings or has warnings). For that, see Grouping conditions.
For three or more alternatives, nest OR inside OR. This filter returns products that have warnings, or are unpublished, or have no category:
filter: { hasWarnings: true, OR: { isPublished: false, OR: { hasCategory: false } } }
NOT
NOT takes a filter that results must not match. This filter returns every product without warnings:
filter: { NOT: { hasWarnings: true } }
The conditions inside NOT combine with AND before they are negated. This filter removes only the products that are unpublished and have warnings, so an unpublished product without warnings is kept:
filter: { NOT: { isPublished: false, hasWarnings: true } }
To remove the products that match either condition, put an OR inside the NOT:
filter: { NOT: { isPublished: false, OR: { hasWarnings: true } } }
Grouping conditions
OR applies to all of the conditions beside it, so you decide what it applies to by deciding what sits beside it. To make an OR apply to only some conditions, move them and the OR into a nested filter under AND:
filter: {
isPublished: true
AND: { visibleInListings: true, OR: { hasWarnings: true } }
}
This means published and (visible in listings or has warnings). The nested filter is evaluated on its own, OR included, and its result is combined with isPublished by AND. A filter nested under NOT is evaluated on its own in the same way, then negated.
Two groups of alternatives
A filter object has only one AND, so it can hold only one group that way. To require two groups of alternatives, such as (visible in listings or has warnings) and (published or has no category), put the second group under NOT twice. NOT of NOT of a group is the group itself:
filter: {
AND: { visibleInListings: true, OR: { hasWarnings: true } }
NOT: { NOT: { isPublished: true, OR: { hasCategory: false } } }
}
How one filter is evaluated
Every filter object, at any depth, is evaluated as:
(field AND field AND … AND <AND filter> AND NOT <NOT filter>) OR <OR filter>
| Step | What is applied | How it combines with the result so far |
|---|---|---|
| 1 | Each field you set, and the filters nested under AND and NOT. Each nested filter is evaluated on its own first, and the NOT filter is then negated. | AND |
| 2 | The filter nested under OR, evaluated on its own | OR |
| 3 | DISTINCT, if true | Removes repeated results |
To build a condition you have written with parentheses, make each parenthesized group a nested filter: under AND for the first group, under NOT: { NOT: … } for a second, and under OR for an alternative to everything else at that level.
DISTINCT
DISTINCT: true returns each matching result at most once, by adding DISTINCT to the database query. You only need it if a result appears more than once in a list. Some filters already remove repeats themselves: on products, collections and search do. DISTINCT adds work to the query, so leave it unset unless you see repeats.
Filters narrow what you can see
Visibility rules and seller scoping are applied to your request separately from your filter, and your filter is combined with them by AND. So an OR cannot reach past them: a buyer's products query returns only the products buyers can see, whatever its OR filter matches.
Two fields also select what you can see, at the top level of the filter only:
- On
products,allowSellerVariants: trueasks for the cross-sell catalog when the marketplace enables master products. A seller's staff then see every seller's products that allow seller variants, not only their own. - On
sellers,hasCrossSellProducts: truelets a caller without marketplace permission list the sellers that offer cross-sell products, and only those sellers.
Passing a filter as a variable
A filter can be passed as a variable, like any other argument. This keeps the query text fixed while the filter changes:
query Products($filter: ProductFilterInput) {
products(first: 20, filter: $filter) {
edges {
node {
id
name
}
}
}
}
Variables:
{
"filter": {
"isPublished": true,
"AND": { "visibleInListings": true, "OR": { "hasWarnings": true } }
}
}
Finding the fields of a filter
Each filter input's own fields are listed in the API reference, for example ProductFilterInput. In GraphiQL, start typing inside filter: { } to list them, and open the Docs panel to read their descriptions.