Filters and sorting
The `query` filter format the collection, search and zone routes accept, how clauses combine, the facet counts, and the sort names, including Shopify's.
Filtering collection, search and zone results
The collection, search and zone routes take filters in one query parameter, query: a JSON array of
clauses, URL-encoded.
const query = [
{ type: 'tag', condition: 'equals', value: ['linen', 'cotton'] },
{ type: 'min_price', condition: 'between', value: ['20', '100'] },
];
const url = `https://mercury.plutocracy.io/search/query/shirt?take=24&query=${encodeURIComponent(JSON.stringify(query))}`;
Each clause has a type, a condition, a value array of strings, and an optional disjunctive flag.
If query is not valid JSON or not an array, it is ignored, so a bad filter never empties a page. A single
clause that can't be used (no type, an empty value, a number that isn't one, an unknown type) is skipped
and the rest still apply.
type | Matches | Conditions |
|---|---|---|
tag | Shopify product tags | equals, contains (the same for tags), not_equals, not_contains |
vendor, type, title | text fields | equals and not_equals match the exact phrase; contains and not_contains match words |
id | product ids | (none; an empty list matches nothing) |
min_price, variant_price | the product's lowest price, in major units ("49.95") | less_than, more_than (or greater_than), between, equals |
variant_compare_at_price | the lowest compare-at price, in major units | as above |
price | the lowest price, in cents ("4995"): the kit's own operator | as above |
total_stock | total inventory | as above |
variant_inventory | total inventory above the value | (none) |
is_price_reduced | products on sale | is_not_set inverts it |
fuzzy | title words within one typo | (none) |
Conditions are lowercase: BETWEEN is not understood. Two values with no condition mean between.
How clauses combine
- Values within a clause are ORed:
tag equals [linen, cotton]matches either tag. Set"disjunctive": falseon the clause to require all of them. - Clauses are ANDed, except that a clause with
"disjunctive": trueis ORed with the clause before it. That is how a sidebar expresses "(colour red OR blue) AND size M".
Custom facet types a store defines in its grid config are not filter types here: filter them with the tag the facet is built from.
Facets
Every page response includes facets: counts for the tags, vendors and types in the result set,
which a sidebar renders as checkboxes. The store's grid config (send grid_config=1) maps raw tags to
facet groups, colours and sizes.
Sorting
Send sort with one of Mercury's sort names:
sort | Order |
|---|---|
newest | created date, newest first |
oldest | created date, oldest first |
az, za | title |
priceLow, priceHigh | lowest price |
manual, best-selling | the collection's own order (collections only) |
random | collections: the page is shuffled after fetching. Search: the same as newest |
On search, no sort (or a name not in this table) gives relevance order.
Sorting collections
- With no
sort, a collection uses its own Shopify sort order, translated:alpha-asc→az,alpha-desc→za,created-asc→oldest,created-desc→newest,price-asc→priceLow,price-desc→priceHigh, andmanualandbest-selling→ the collection's order. The response'ssort_orderis reported in Mercury's names. ?sort=only understands Mercury's names. A Shopify name (or anything unknown) falls back to the collection's manual order, so translate before you send.
Zones are ordered by the zone itself: the merchant's picks, or the collection's own order for a collection zone.
Shopify's sort names
Shopify themes use their own names (price-ascending, title-descending, created-descending...). The
routes only understand Mercury's names in ?sort=, so translate in your theme. A Shopify name sent as-is is
not an error: it gives relevance order on search and manual order on a collection.
const toMercury = { 'price-ascending': 'priceLow', 'price-descending': 'priceHigh', 'title-ascending': 'az',
'title-descending': 'za', 'created-ascending': 'oldest', 'created-descending': 'newest', 'manual': 'manual',
'best-selling': 'best-selling' };
const sort = toMercury[shopifySort]; // undefined: leave sort out (relevance on search, the collection's own order)