Query<R, J>
The Query class provides a configurable interface for executing raw SurrealQL statements with support for streaming, batch processing, and response handling. It extends Promise, allowing you to await it directly or use specialized methods.
Returned by: SurrealQueryable.query()
Source: query/query.ts
Type Parameters
R extends unknown[] - Array of result types for each query statementJ extends boolean - Boolean indicating if result is JSON (default: false)
Methods
.collect()
Collect and return the results of all queries at once. If any query fails, the promise rejects.
You can optionally specify which query indexes to collect.
Method Syntax
query.collect<T>(...queryIndexes?)
Parameters
| Parameter | Type | Description |
|---|
queryIndexes optional | number[] | Specific query indexes to collect. If omitted, collects all. |
Type Parameters
T extends unknown[] - Override result types
Returns
Promise<Collect<T, J>> - Array of results
Examples
Single Query
const result = await db.query('SELECT * FROM users').collect();
console.log(result);
Multiple Queries with Types
const [users, posts] = await db.query<[User[], Post[]]>(`
SELECT * FROM users;
SELECT * FROM posts;
`).collect();
Collect Specific Queries
const [users] = await db.query(`
SELECT * FROM users;
SELECT * FROM posts;
SELECT * FROM comments;
`).collect<[User[]]>(0);
With Bindings
const result = await db.query(
'SELECT * FROM users WHERE age > $age',
{ age: 18 }
).collect();
.stream()
Stream response frames as they are received from the database.
Each iteration yields a value frame, error frame, or done frame.
Method Syntax
query.stream()
Returns
AsyncIterableIterator<Frame<unknown, J>> - Async iterator of frames
Each frame is one of three types, distinguished by the type property:
Value Frame (type: 'value')
frame.value - The result dataframe.query - Query index
Error Frame (type: 'error')
frame.error - Error informationframe.query - Query index
Done Frame (type: 'done')
frame.query - Query index that completed
Examples
Stream Processing
for await (const frame of db.query('SELECT * FROM users').stream()) {
if (frame.type === 'value') {
console.log('Received data:', frame.value);
} else if (frame.type === 'error') {
console.error('Query error:', frame.error);
} else if (frame.type === 'done') {
console.log('Query complete');
}
}
Process Large Results
let count = 0;
for await (const frame of db.query('SELECT * FROM large_table').stream()) {
if (frame.type === 'value') {
await processRecord(frame.value);
count++;
}
}
console.log(`Processed ${count} records`);
.responses()
Get individual response objects for each query statement, including success/failure status.
Method Syntax
query.responses<T>()
Type Parameters
T extends unknown[] - Override result types
Returns
Promise<Responses<T, J>> - Array of QueryResponse objects
Examples
Handle Individual Responses
const responses = await db.query(`
SELECT * FROM users;
INVALID QUERY;
SELECT * FROM posts;
`).responses();
for (const [index, response] of responses.entries()) {
if (response.success) {
console.log(`Query ${index} succeeded:`, response.result);
} else {
console.error(`Query ${index} failed:`, response.error.message);
}
}
Check Query Statistics
const responses = await db.query('SELECT * FROM users').responses();
for (const response of responses) {
if (response.success && response.stats) {
console.log('Records scanned:', response.stats.recordsScanned);
console.log('Duration:', response.stats.duration);
}
}
.json()
Configure the query to return results as JSON strings.
Method Syntax
query.json()
Returns
Query<R, true> - Query returning JSON strings
Example
const jsonResults = await db.query('SELECT * FROM users').json().collect();
console.log(typeof jsonResults[0]);
Complete Examples
Basic Query Execution
import { Surreal } from 'surrealdb';
const db = new Surreal();
await db.connect('ws://localhost:8000');
const result = await db.query('SELECT * FROM users').collect();
console.log(result[0]);
const result = await db.query('SELECT * FROM users');
Parameterized Queries
const result = await db.query(
'SELECT * FROM users WHERE age > $age AND status = $status',
{ age: 18, status: 'active' }
).collect();
import { surql } from 'surrealdb';
const minAge = 18;
const result = await db.query(
surql`SELECT * FROM users WHERE age > ${minAge}`
).collect();
Multiple Statements
const [users, posts, comments] = await db.query<[User[], Post[], Comment[]]>(`
SELECT * FROM users;
SELECT * FROM posts WHERE published = true;
SELECT * FROM comments WHERE approved = true;
`).collect();
console.log('Users:', users);
console.log('Posts:', posts);
console.log('Comments:', comments);
Streaming Large Results
const query = db.query('SELECT * FROM large_table');
for await (const frame of query.stream()) {
if (frame.type === 'value') {
await processChunk(frame.value);
} else if (frame.type === 'error') {
console.error('Error:', frame.error);
break;
}
}
Error Handling with Responses
const responses = await db.query(`
CREATE users:john SET name = 'John';
CREATE users:john SET name = 'Duplicate';
SELECT * FROM users:john;
`).responses();
for (const [i, response] of responses.entries()) {
if (response.success) {
console.log(`Query ${i} OK:`, response.result);
} else {
console.log(`Query ${i} failed:`, response.error.message);
}
}
Transaction Queries
const txn = await db.beginTransaction();
try {
const [created, updated] = await txn.query<[User, User]>(`
CREATE users:new SET name = 'New User';
UPDATE users:john SET updated_at = time::now();
`).collect();
await txn.commit();
} catch (error) {
await txn.cancel();
}
Complex Query with Statistics
const responses = await db.query(`
SELECT * FROM users WHERE age > 18;
SELECT count() FROM users GROUP BY status;
`).responses();
for (const response of responses) {
if (response.success && response.stats) {
console.log('Execution time:', response.stats.duration);
console.log('Records scanned:', response.stats.recordsScanned);
console.log('Bytes received:', response.stats.bytesReceived);
}
}
Conditional Logic
const status = 'active';
const minAge = 18;
const result = await db.query(
surql`
LET $active_users = SELECT * FROM users WHERE status = ${status};
LET $adult_users = SELECT * FROM users WHERE age >= ${minAge};
RETURN {
active: $active_users,
adults: $adult_users,
both: SELECT * FROM $active_users WHERE age >= ${minAge}
};
`
).collect();
Data Migration
const migration = await db.query(`
-- Add new field to all users
UPDATE users SET new_field = 'default_value';
-- Migrate data format
UPDATE users SET profile = {
bio: bio,
avatar: avatar_url
};
-- Remove old fields
UPDATE users UNSET bio, avatar_url;
`).collect();
console.log('Migration complete');
Streaming with Progress
let totalRecords = 0;
let queriesCompleted = 0;
for await (const frame of db.query('SELECT * FROM users; SELECT * FROM posts;').stream()) {
if (frame.type === 'value') {
totalRecords += frame.value.length;
console.log(`Received ${frame.value.length} records`);
} else if (frame.type === 'done') {
queriesCompleted++;
console.log(`Query ${frame.query} completed`);
}
}
console.log(`Total: ${totalRecords} records from ${queriesCompleted} queries`);
Best Practices
1. Use Parameterization
const result = await db.query(
'SELECT * FROM users WHERE name = $name',
{ name: userName }
).collect();
const result = await db.query(
surql`SELECT * FROM users WHERE name = ${userName}`
).collect();
const result = await db.query(
`SELECT * FROM users WHERE name = '${userName}'`
).collect();
2. Handle Errors Appropriately
const responses = await db.query(multiStatementQuery).responses();
for (const response of responses) {
if (!response.success) {
handleError(response.error);
}
}
try {
const results = await db.query(query).collect();
} catch (error) {
}
3. Use Streaming for Large Results
for await (const frame of db.query('SELECT * FROM large_table').stream()) {
if (frame.type === 'value') {
await processChunk(frame.value);
}
}
const [large] = await db.query('SELECT * FROM large_table').collect();
4. Leverage Type Parameters
const [users, posts] = await db.query<[User[], Post[]]>(`
SELECT * FROM users;
SELECT * FROM posts;
`).collect();
users[0].name;
posts[0].title;
See Also