BoundQuery<R>The BoundQuery class represents a parameterized 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 bindings Parameters Parameter Type Description query string | BoundQueryQuery 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 queryThe 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'
bindingsA copy of the parameter bindings.
Type: Record<string, unknown>
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 otherBoundQuery | string | TemplateStringsArrayQuery 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 } ` ;
.bind()Add or update a parameter binding.
Parameters Parameter Type Description key stringParameter name (without $ prefix). value unknownParameter value.
Returns this - Chainable
Example const query = new BoundQuery ( 'SELECT * FROM users WHERE age > $age' ) ; query . bind ( 'age' , 18 ) ; query . bind ( 'status' , 'active' ) ; const [ users ] = await db . query ( query ) . collect ( ) ;
.toString()Get the query string.
Returns string - The query string
Complete Examples Basic Parameterized 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 ( ) ; 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
expr - Expression builder