Restful Filtering Sorting
title: "RESTful Filtering and Sorting — Query Parameter Conventions" description: "RESTful filtering and sorting use query parameters like ?status=active&sort_by=name&order=asc for clean, predictable resource list manipulation." date: 2026-06-28 lastmod: 2026-06-28 weight: 16 tags: [apis, restful] }
RESTful filtering and sorting use query parameters to refine resource collections with field-based filters, sorting directives, and partial response selection.
What You'll Learn
- Filter parameter conventions
- Sorting parameters
- Partial response with fields
Why It Matters
Consistent filtering and sorting conventions let clients get exactly the data they need, reducing payload size and improving performance.
Code Examples
@app.route('/users')
def list_users():
# Build query from filter params
query = "SELECT * FROM users WHERE 1=1"
params = []
# Exact match filters
if status := request.args.get('status'):
query += " AND status = ?"
params.append(status)
if role := request.args.get('role'):
query += " AND role = ?"
params.append(role)
# Range filters
if min_age := request.args.get('min_age'):
query += " AND age >= ?"
params.append(int(min_age))
if max_age := request.args.get('max_age'):
query += " AND age <= ?"
params.append(int(max_age))
# Search filter
if search := request.args.get('q'):
query += " AND (name LIKE ? OR email LIKE ?)"
params.extend([f"%{search}%", f"%{search}%"])
# Sorting
sort_by = request.args.get('sort_by', 'id')
sort_order = request.args.get('sort_order', 'asc')
allowed_sorts = ['id', 'name', 'email', 'created_at']
if sort_by in allowed_sorts:
order = 'DESC' if sort_order == 'desc' else 'ASC'
query += f" ORDER BY {sort_by} {order}"
# Partial response
fields = request.args.get('fields')
if fields:
allowed_fields = ['id', 'name', 'email', 'status', 'role', 'created_at']
selected = [f for f in fields.split(',') if f in allowed_fields]
if selected:
query = f"SELECT {','.join(selected)} FROM users WHERE 1=1"
users = db.execute(query, params)
return jsonify(users)
// Filtering middleware
function parseFilters(req, res, next) {
const filters = {};
// Parse filter params
for (const [key, value] of Object.entries(req.query)) {
if (['sort_by', 'sort_order', 'page', 'limit', 'fields'].includes(key)) continue;
// Handle operators
if (key.endsWith('__gte')) {
filters[`${key.slice(0, -5)}__gte`] = value;
} else if (key.endsWith('__lte')) {
filters[`${key.slice(0, -5)}__lte`] = value;
} else {
filters[key] = value;
}
}
req.filters = filters;
req.sortBy = req.query.sort_by || 'id';
req.sortOrder = req.query.sort_order || 'asc';
req.fields = req.query.fields ? req.query.fields.split(',') : null;
next();
}
app.get('/api/users', parseFilters, (req, res) => {
let users = db.getUsers(req.filters, req.sortBy, req.sortOrder, req.fields);
res.json(users);
});
Common Mistakes
1. Inconsistent Filter Parameter Names
Mix of status, filter[status], and status_id across endpoints.
2. No Allowed Sort Fields
Sorting by unindexed columns causes performance issues.
3. Case-Sensitive Filters
Status filter matching active but not Active.
4. No Filter Validation
Invalid filter values cause SQL errors or expose data.
5. Mixing Filter and Pagination Params
Keep filters and pagination separate and consistent.
Practice Questions
- What parameter naming convention is recommended for filters?
- How do you implement range filters?
- Why validate sort fields?
- What is a partial response?
- How do you handle search queries with filtering?
Answers:
- Flat parameter names:
?status=active&role=admin. - With min/max params:
?min_price=10&max_price=100. - To prevent sorting on unindexed or sensitive columns.
?fields=id,name,emailreturns only specified fields.- Use a
qparameter for full-text search combined with structured filters.
Challenge: Design a consistent filtering and sorting interface for a products API. Support filters by category, price range, and search with sorting options.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro