URL Query Syntax
Experimental
The DB integrations layer is experimental. APIs and annotations described in this section may change in future releases.
The HTTP controllers (AsDbController and AsDbReadableController) accept a rich URL query syntax for filtering, sorting, pagination, and relation loading — powered by @uniqu/url. Filters and controls are encoded directly into the query string using a compact, expressive format that all database adapters understand.
Basic Filtering
Filter records by matching field values. Multiple conditions are combined with & (AND):
GET /query?status=active
GET /query?status=active&priority=highComparison Operators
Compare fields against values using inline operators:
?status!=done # not equal
?priority>3 # greater than
?priority>=3 # greater than or equal
?priority<5 # less than
?priority<=5 # less than or equalThese work with numeric fields, dates, and any comparable type supported by the adapter.
Set Operators
Match against a set of values using curly braces:
?role{Admin,Editor} # IN (role is Admin or Editor)
?status!{Draft,Deleted} # NOT INThe IN operator matches records where the field equals any value in the comma-separated list. NOT IN excludes records matching any value in the set.
Range (Between)
Filter a field within a numeric or date range:
?25<age<35 # exclusive range
?25<=age<=35 # inclusive rangeThe value is placed between two bounds. Mix < and <= as needed (e.g., 25<=age<35).
Pattern Matching
Match a field against a regular expression:
?name~=/^Al/i # regex matchThe pattern follows /pattern/flags format. Common flags include i (case-insensitive). Regex support depends on the database adapter — MongoDB supports full PCRE, while SQLite uses LIKE-based approximation for simple patterns.
Existence
Check whether fields are present (non-null) or absent (null):
?$exists=email,phone # fields must exist (not null)
?$!exists=deletedAt # field must not exist (is null)Multiple fields can be comma-separated. A field "exists" when its value is not null.
Null Values
Explicitly match null values:
?assigneeId=null # field is nullThe literal null is parsed as a null value, not the string "null".
Logical Operators
Combine conditions with AND, OR, NOT, and grouping:
?status=todo&priority=high # AND (tighter binding)
?status=done^priority=low # OR (looser binding)
?(status=todo^status=in_progress) # grouped OR
?!(status=done) # NOTOperator precedence: & (AND) binds tighter than ^ (OR). This means:
?status=done^priority=high&role=adminis interpreted as:
status=done OR (priority=high AND role=admin)Use parentheses to override default precedence:
?(status=todo^status=in_progress)&priority=highThis matches records where status is todo or in_progress, and priority is high.
Control Keywords
Special $-prefixed parameters configure query behavior rather than filtering data.
Projection ($select)
Control which fields are returned:
?$select=id,title,status # include only these fields
?$select=-password,-secret # exclude these fieldsInclude mode returns only the listed fields. Exclude mode (prefix with -) returns all fields except the listed ones.
Avoid mixed mode
Mixing includes and excludes (e.g., $select=name,-password) produces unpredictable results depending on the adapter. Use either include-only or exclude-only.
Sorting ($sort)
Order results by one or more fields:
?$sort=name # ascending
?$sort=-createdAt # descending (prefix -)
?$sort=status,-priority # multi-field sortFields are comma-separated. Prefix a field with - for descending order.
Pagination — Offset-Based (for /query)
Use $limit and $skip for offset-based pagination:
?$limit=20 # max records
?$skip=40 # offsetPagination — Page-Based (for /pages)
Use $page and $size for page-based pagination:
?$page=2&$size=10 # page number + page sizePages are 1-based. The /pages endpoint returns paginated results with metadata (total count, page info).
Count ($count)
Return only the count of matching records, without data:
?$count # return count instead of dataSearch ($search)
Perform full-text search:
?$search=mongodb tutorial # fulltext search
?$index=product_search # named search indexFull-text search support depends on the adapter. MongoDB supports Atlas Search with named indexes. SQLite does not provide built-in fulltext search. When search is not supported by the adapter, the endpoint returns a 400 or 501 error.
Relation Loading ($with)
Load related data inline by specifying navigational relations declared with @db.rel.to, @db.rel.from, or @db.rel.via in your schema.
Single relation:
?$with=author # single relationMultiple relations:
?$with=author,comments # multiple relationsWith controls — apply sorting, limits, or other controls to a specific relation using parentheses:
?$with=posts($limit=5&$sort=-createdAt) # with controlsNested relations — load relations of relations:
?$with=posts($with=comments) # nested relationsFiltered with nested — combine filters, controls, and nesting inside parentheses:
?$with=posts(status=published&$with=comments($limit=3)) # filtered + nestedParentheses contain a sub-query for the relation. All filter and control syntax described on this page works inside relation sub-queries.
FK fields auto-included
When using $select alongside $with, foreign key fields needed for joining are automatically included — even if not explicitly listed or explicitly excluded. This ensures relations resolve correctly.
Comprehensive Examples
Simple list — active items, sorted by recency, limited to 10:
GET /query?status=active&$sort=-createdAt&$limit=10Paginated with search — full-text search with page-based pagination:
GET /pages?$search=typescript&$page=1&$size=20&$sort=-relevanceComplex filtered with relations — high-priority incomplete tasks with projection and relations:
GET /query?status!=done&priority>=3&$select=id,title,status&$with=assignee,tags&$sort=-priority,title&$limit=50Nested relation loading — projects and comments with their own projections and controls:
GET /query?$with=project($select=id,title),comments($sort=-createdAt&$limit=5&$with=author($select=name))Count with filter — count completed tasks without returning data:
GET /query?completed=true&$countExcluding sensitive fields:
GET /query?$select=-password,-secret,-internalNotesNext Steps
- Customization & Hooks — Interceptors and overrides
- HTTP Controllers — REST endpoint reference and setup
- Queries & Filters — Programmatic query API (non-HTTP)