The BoundQuery class represents a parameterised SurrealQL query with bound variables, providing safe query composition and preventing SQL injection.
Import:
import { BoundQuery } from 'surrealdb';Source: utils/bound-query.ts
Type parameters
R extends unknown[]- Array of result types for the query
Constructor
new BoundQuery(query?, bindings?)
Create a new bound query.
new BoundQuery() // Empty query
new BoundQuery(boundQuery) // Clone existing
new BoundQuery(query, bindings?) // From string and bindingsParameters
Parameter | Type | Description |
|---|---|---|
query | string | BoundQuery | Query string or existing BoundQuery to clone. |
bindings | Record<string, unknown> | Parameter bindings. |
Examples
// Empty query
const query = new BoundQuery();
// From string
const query = new BoundQuery('SELECT * FROM users');
// With bindings
const query = new BoundQuery(
'SELECT * FROM users WHERE age > $age',
{ age: 18 }
);
// Clone existing
const clone = new BoundQuery(existingQuery);Properties
query
The query string with parameter placeholders.
Type: string
const query = new BoundQuery(
'SELECT * FROM users WHERE age > $age',
{ age: 18 }
);
console.log(query.query);
// 'SELECT * FROM users WHERE age > $age' bindings
A copy of the parameter bindings.
**Type:** `Record`
console.log(query.bindings);
// { age: 18 }Methods
.append()
Append another query or string to this query.
query.append(other)
query.append(queryString, bindings?)
query.append`template ${value}`Parameters
Parameter | Type | Description |
|---|---|---|
other | BoundQuery | string | TemplateStringsArray | Query to append. |
bindings | Record<string, unknown> | Bindings for the appended query. |
Returns
this - Chainable
Examples
const base = new BoundQuery('SELECT * FROM users WHERE 1=1');
const filter = new BoundQuery(' AND age > $age', { age: 18 });
base.append(filter);const query = new BoundQuery('SELECT * FROM users');
query.append(' WHERE active = $active', { active: true });const query = new BoundQuery('SELECT * FROM users');
const status = 'active';
query.append` WHERE status = ${status}`; .toString()
Get the query string.
query.toString()Returns
string - The query string
Complete examples
Basic parameterised query
import { BoundQuery } from 'surrealdb';
const query = new BoundQuery(
'SELECT * FROM users WHERE age >= $minAge AND status = $status',
{
minAge: 18,
status: 'active'
}
);
const [users] = await db.query(query).collect();Building queries incrementally
// Start with base query
const query = new BoundQuery('SELECT * FROM products WHERE 1=1');
// Add conditions dynamically
if (category) {
query.append(' AND category = $category', { category });
}
if (minPrice) {
query.append(' AND price >= $minPrice', { minPrice });
}
if (maxPrice) {
query.append(' AND price <= $maxPrice', { maxPrice });
}
query.append(' ORDER BY created_at DESC LIMIT $limit', { limit: 10 });
const [products] = await db.query(query).collect();Query builder pattern
class QueryBuilder {
private query: BoundQuery;
constructor(table: string) {
this.query = new BoundQuery(`SELECT * FROM ${table} WHERE 1=1`);
}
where(field: string, value: unknown): this {
this.query.append(` AND ${field} = $${field}`,
{ [field]: value });
return this;
}
limit(count: number): this {
this.query.append(' LIMIT $limit', { limit: count });
return this;
}
build(): BoundQuery {
return this.query;
}
}
// Usage
const builder = new QueryBuilder('users');
const query = builder
.where('status', 'active')
.where('verified', true)
.limit(10)
.build();
const [users] = await db.query(query).collect();Reusable query fragments
// Define reusable fragments
const activeFilter = new BoundQuery('status = $status',
{ status: 'active' });
const verifiedFilter = new BoundQuery('verified = $verified',
{ verified: true });
// Combine them
const query = new BoundQuery('SELECT * FROM users WHERE ');
query.append(activeFilter);
query.append(' AND ');
query.append(verifiedFilter);
const [users] = await db.query(query).collect();Complex multi-statement query
const userId = new RecordId('users', 'john');
const postData = {
title: 'My Post',
content: 'Content here'
};
const query = new BoundQuery();
query.append('BEGIN TRANSACTION;');
query.append(
'UPDATE $userId SET post_count += 1;',
{ userId }
);
query.append(
'CREATE posts SET author = $author, title = $title,
content = $content;',
{
author: userId,
title: postData.title,
content: postData.content
}
);
query.append('COMMIT TRANSACTION;');
await db.query(query).collect();Pagination helper
function paginatedQuery(
table: string,
page: number,
pageSize: number,
filters?: Record<string, unknown>
): BoundQuery {
const query = new BoundQuery(`SELECT * FROM ${table} WHERE 1=1`);
if (filters) {
for (const [key, value] of Object.entries(filters)) {
query.append(` AND ${key} = $${key}`, { [key]: value });
}
}
const offset = (page - 1) * pageSize;
query.append(' START $offset LIMIT $limit', {
offset,
limit: pageSize
});
return query;
}
// Usage
const query = paginatedQuery('users', 2, 20, { status: 'active' });
const [users] = await db.query(query).collect();Best practices
1. Use surql template instead
For most cases, the surql template is easier:
// Good: surql template (recommended)
const query = surql`SELECT * FROM users WHERE age > ${age}`;
// Also good: BoundQuery (more manual)
const query = new BoundQuery(
'SELECT * FROM users WHERE age > $age',
{ age }
);2. Validate parameter names
// Good: Consistent parameter naming
const query = new BoundQuery(
'SELECT * FROM users WHERE age > $age AND status = $status',
{ age: 18, status: 'active' }
);
// Avoid: Mismatched names
const query = new BoundQuery(
'SELECT * FROM users WHERE age > $minAge',
{ age: 18 } // Wrong key name
);3. Use append() for dynamic queries
// Good: Incremental building
const query = new BoundQuery('SELECT * FROM users WHERE 1=1');
if (filter) {
query.append(' AND status = $status', { status: filter });
}
// Avoid: String concatenation
let queryStr = 'SELECT * FROM users WHERE 1=1';
if (filter) {
queryStr += ` AND status = '${filter}'`; // Unsafe!
}See also
surql - Template tag for queries
Query - Query execution class
SurrealQueryable.query() - Query method
expr - Expression builder