Skip to content

Filtering

intermediate2 min read
  • REST API
  • Node.js

Letting clients narrow a collection to the records they want through query parameters, safely translated into database conditions.

What you'll understand

  • How clients ask an API for a subset of a collection
  • How filter parameters map to database conditions
  • Why filters must be validated and whitelisted

Explanation

Filtering lets a client ask for only the records that match some criteria rather than the whole collection. It is expressed through query parameters on a list endpoint: GET /users?status=active&role=admin asks for active admins. On the server, each recognised parameter becomes a condition in the database query, narrowing the result set before it is returned.

The mapping from parameters to conditions is where care is needed. You decide which fields are filterable and how each parameter translates, an exact match, a range, a contains search, and you build the query from those recognised parameters. This is closely tied to pagination and sorting: filtering chooses which rows, sorting orders them, and pagination returns them a page at a time (see Related Topics).

Filtering is also a security boundary. Never turn raw query parameters directly into a query, and never let a client filter on arbitrary fields, both invite injection and data exposure. Whitelist the fields a client may filter on, validate the values, and pass them as parameters to the database, never as concatenated strings.

Examples

This TypeScript example builds a filter from whitelisted parameters and passes values safely to Prisma:

const where: Record<string, unknown> = {};
if (req.query.status) where.status = String(req.query.status);
if (req.query.role) where.role = String(req.query.role);

const users = await prisma.user.findMany({ where });

Only the status and role fields are filterable here; any other query parameter is ignored rather than trusted.

Common mistakes

  • Concatenating query parameters straight into a query, opening the door to injection.
  • Letting clients filter on any field, including internal ones.
  • Skipping validation of filter values before using them.
  • Treating a missing or empty filter as a match-nothing instead of no-constraint.

Best practices

  • Whitelist exactly which fields may be filtered.
  • Validate filter values and pass them as parameters, never concatenated.
  • Define how each parameter maps to a condition (exact, range, contains).
  • Combine filtering with sorting and pagination for predictable list endpoints (see Related Topics).

Further reading

Related topics