Guides
Every collection in your store — standard models, custom models, and app-defined models alike — supports a rich query language through the Backend API. This guide covers the query features that go beyond basic listing: filtering, expanding linked records, including related data in a single request, aggregations, and search. Examples use the swell-node client, and the same parameters work as query strings on direct HTTP requests.
The where parameter filters records using MongoDB-style query operators such as $eq, $ne, $gt, $in, and $or, including on nested fields with dot notation.
// Active products over $50
await swell.get('/products', {
where: {
active: true,
price: { $gt: 50 },
},
});
// Orders that are either on hold or unpaid
await swell.get('/orders', {
where: {
$or: [{ hold: true }, { paid: false }],
},
});Use sort with a field name and direction, limit to control page size (up to 1,000 records per request), and page to paginate through results.
await swell.get('/orders', {
where: { paid: true },
sort: 'date_created desc',
limit: 50,
page: 2,
});Most models reference other models through link fields — an order links to its account, a review links to its product. The expand parameter resolves those links in the same request. Expand multiple links with a comma-separated list, and nest through links with dot notation (up to 5 levels deep).
// Expand the order's account, and each item's product
await swell.get('/orders', {
expand: 'account, items.product',
});When the expanded link is a collection, Swell returns up to 5 records by default. Specify a different count with a colon:
// Expand up to 20 variants on the product
await swell.get('/products/{id}', {
id: '5f63e175e7eed80c11766c83',
expand: 'variants:20',
});While expand follows link fields defined on the model, include attaches the result of an arbitrary sub-query to each record in the response — any endpoint, with its own query parameters. Each include has a url to request, optional params that map fields from the parent record into the sub-query, and optional data with fixed query parameters.
// List accounts, each with their most recent order attached
await swell.get('/accounts', {
limit: 25,
include: {
last_order: {
url: '/orders/:last',
params: {
account_id: 'id',
},
data: {
fields: 'number, grand_total, date_created',
},
},
},
});In this example, params: { account_id: 'id' } sets each sub-query's account_id filter to the parent account's id. The result is attached to each record under the include's key — here, last_order. An include can also define conditions evaluated against the parent record, so the sub-query only runs when the criteria match.
Every collection supports a set of special endpoints for aggregate results:
- /:count — the number of records matching a query.
- /:first and /:last — the first or most recent matching record.
- /:group — aggregate values across matching records, using MongoDB-style accumulators such as $sum.
// How many paid orders does this customer have?
const count = await swell.get('/orders/:count', {
account_id: accountId,
canceled: { $ne: true },
});
// The customer's most recent order
const lastOrder = await swell.get('/orders/:last', {
account_id: accountId,
});
// Total sales and order count for paid orders
const stats = await swell.get('/orders/:group', {
where: { paid: true },
count: { $sum: 1 },
total_sales: { $sum: 'grand_total' },
});With /:group, each key in the query besides where becomes a field in the result — the example above returns an object like { count: 152, total_sales: 8940.5 }. Note that for /:count, /:first, and /:last, top-level query fields act as the filter directly.
The search parameter matches a term across a model's searchable fields, and combines with where filters.
await swell.get('/products', {
search: 'organic cotton',
where: { active: true },
});For performance — especially inside app functions and includes — use the fields parameter to return only what you need.
await swell.get('/products', {
fields: 'name, slug, price',
limit: 100,
});These parameters work on every collection, including custom and app-defined models. For per-model fields and endpoints, see the Backend API reference. For querying from a storefront with public keys, see the Frontend API, which supports a compatible query syntax limited by public permissions.