Skip to main content

Documentation

Querying

Query patterns and best practices

Querying

🔍 Query Patterns & Best Practices

Implemented by query_handler / get_by_id_handler in stackhouse/src/api/handlers.rs, routed at stackhouse/src/api/routes.rs:17-23.

REST API Queries

# Get all documents (default limit: 100, hard cap: 1000)
GET /v1/query/:collection

# Get specific document
GET /v1/query/:collection/:id

# With pagination
GET /v1/query/:collection?limit=100&offset=0

# With ordering — param is `order_dir`, not `order`
GET /v1/query/:collection?order_by=created_at&order_dir=desc

Response shape: {"success": true, "data": [...], "count": N, "collection": "..."}.

Filtering

Equality filters are applied server-side via query-string parameters — any param that isn't one of limit, offset, order_by, order_dir is treated as a column = value filter, AND-ed together, with the column name validated as a safe SQL identifier before use:

# WHERE active = 'true'
GET /v1/query/users?active=true

# WHERE active = 'true' AND role = 'admin'
GET /v1/query/users?active=true&role=admin

All filter values are compared as text equality — there is no operator syntax (>, <, LIKE, etc.) via this endpoint. For anything beyond equality, use the raw SQL endpoint below.

// Client-side filtering is only needed for logic the query-string API
// doesn't support (e.g. non-equality comparisons):
const users = await fetch('/v1/query/users?active=true')
  .then(r => r.json())
  .then(data => data.data);

Advanced Patterns

Raw SQL access

POST /v1/sql/query
{"query": "SELECT * FROM users WHERE age > 25"}

Gated behind raw_sql_enabled (off by default) and admin auth — see API Reference for current restrictions on this endpoint (destructive-statement filtering, etc).

Performance Tips

Do

✅ Use specific ID lookups (GET /v1/query/:collection/:id) ✅ Use the built-in limit/offset (max 1000 rows per request) ✅ Create indexes on frequently queried fields

Avoid

❌ Large result sets — 1000 rows is a hard server-side cap


Next: Indexing