RecordId<Tb, Id>The RecordId class provides type-safe record identifiers in SurrealDB. Each record ID consists of a table name and an ID value, represented as table:id in SurrealQL.
Import:
import { RecordId } from 'surrealdb';
Source: value/record-id.ts
Tb extends string - The table name (string literal type for type safety)Id - The ID value type (string, number, object, etc.)new RecordId(table, id, validate?)Create a new record identifier.
Syntaxnew RecordId(table, id, validate?)
| Parameter | Type | Description |
|---|---|---|
table required | Tb | The table name. |
id required | Id | The record ID value (string, number, object, array, or RecordId). |
validate optional | boolean | Whether to validate the table name format (default: true). |
// String IDs const user = new RecordId('users', 'john'); const post = new RecordId('posts', '123'); // Numeric IDs const product = new RecordId('products', 42); // Complex/structured IDs const metric = new RecordId('metrics', { service: 'api', timestamp: 1234567890 }); // Array IDs const compound = new RecordId('items', ['type-a', 123]); // Nested RecordId const nested = new RecordId('links', new RecordId('users', 'alice')); // Type-safe with generics const typedUser = new RecordId<'users', string>('users', 'john');
tbThe table name component.
Type: Tb
const userId = new RecordId('users', 'john'); console.log(userId.tb); // 'users'
idThe ID value component.
Type: Id
const userId = new RecordId('users', 'john'); console.log(userId.id); // 'john' const productId = new RecordId('products', 42); console.log(productId.id); // 42
RecordId.parse(string)Parse a record ID from its string representation.
SyntaxRecordId.parse(str)
| Parameter | Type | Description |
|---|---|---|
str required | string | The record ID string (format: table:id). |
RecordId - The parsed record ID
// Parse simple IDs const user = RecordId.parse('users:john'); const post = RecordId.parse('posts:123'); // Parse complex IDs const metric = RecordId.parse('metrics:{ service: "api", time: 1234567890 }'); // Use in queries const userId = RecordId.parse('users:alice'); const user = await db.select(userId);
RecordId.from(value)Create a record ID from various value types.
SyntaxRecordId.from(value)
| Parameter | Type | Description |
|---|---|---|
value required | unknown | Value to convert to RecordId. |
RecordId | undefined - The record ID or undefined if conversion fails
const rid = RecordId.from('users:john'); const same = RecordId.from(new RecordId('users', 'john'));
.toString()Convert the record ID to its string representation.
SyntaxrecordId.toString()
string - String representation in format table:id
const userId = new RecordId('users', 'john'); console.log(userId.toString()); // 'users:john' const productId = new RecordId('products', 42); console.log(productId.toString()); // 'products:42' const complex = new RecordId('items', { type: 'widget', id: 5 }); console.log(complex.toString()); // 'items:{ type: "widget", id: 5 }'
.toJSON()Serialize the record ID for JSON.
SyntaxrecordId.toJSON()
string - JSON-safe string representation
const userId = new RecordId('users', 'john'); console.log(JSON.stringify(userId)); // '"users:john"'
.equals(other)Check if two record IDs are equal.
SyntaxrecordId.equals(other)
| Parameter | Type | Description |
|---|---|---|
other required | unknown | Value to compare. |
boolean - True if equal
const a = new RecordId('users', 'john'); const b = new RecordId('users', 'john'); const c = new RecordId('users', 'jane'); console.log(a.equals(b)); // true console.log(a.equals(c)); // false
import { Surreal, RecordId } from 'surrealdb'; const db = new Surreal(); await db.connect('ws://localhost:8000'); // Create record with specific ID const user = await db.create(new RecordId('users', 'john')) .content({ name: 'John Doe', email: 'john@example.com' }); // Select by record ID const retrieved = await db.select(new RecordId('users', 'john')); // Update by record ID await db.update(new RecordId('users', 'john')) .merge({ status: 'active' }); // Delete by record ID await db.delete(new RecordId('users', 'john'));
interface User { id: RecordId<'users', string>; name: string; email: string; } // TypeScript enforces correct table name const userId: RecordId<'users', string> = new RecordId('users', 'alice'); // This would be a type error: // const wrong: RecordId<'posts', string> = new RecordId('users', 'alice'); const user = await db.select<User>(userId);
// Time-series data with structured IDs const metricId = new RecordId('metrics', { service: 'api', host: 'server-01', timestamp: 1234567890 }); await db.create(metricId).content({ cpu: 45.2, memory: 78.1 }); // Compound keys const sessionId = new RecordId('sessions', { userId: 'john', deviceId: 'device-123' });
// Parse user input const userInput = 'users:john'; const userId = RecordId.parse(userInput); const user = await db.select(userId); // Parse from query results const result = await db.query('SELECT id FROM users:john').collect(); const recordId = RecordId.parse(result[0].id);
// Create relationship using record IDs const from = new RecordId('users', 'john'); const to = new RecordId('posts', '123'); const edge = await db.relate( from, new Table('likes'), to, { timestamp: DateTime.now() } ); console.log('Edge from:', edge.in); // RecordId('users', 'john') console.log('Edge to:', edge.out); // RecordId('posts', '123')
import { Uuid } from 'surrealdb'; // Generate time-ordered IDs const userId = new RecordId('users', Uuid.v7()); // Generate random IDs const sessionId = new RecordId('sessions', Uuid.v4()); await db.create(userId).content({ name: 'Alice', created: DateTime.now() });
// Validate table names (enabled by default) try { const invalid = new RecordId('invalid-table!', 'id'); } catch (error) { console.error('Invalid table name'); } // Skip validation const unvalidated = new RecordId('any-name', 'id', false);
The RecordIdRange class represents a range of record IDs for querying multiple records.
new RecordIdRange(table, begin, end)
| Parameter | Type | Description |
|---|---|---|
table required | string | The table name. |
begin required | string | number | RecordId | Start of the range (inclusive). |
end required | string | number | RecordId | End of the range (exclusive). |
import { RecordIdRange } from 'surrealdb'; // Select range of users from 'a' to 'f' const range = new RecordIdRange('users', 'a', 'f'); const users = await db.select(range); // Numeric range const numRange = new RecordIdRange('items', 1, 100); const items = await db.select(numRange); // Update range await db.update(new RecordIdRange('users', 'a', 'f')) .merge({ verified: true }); // Delete range await db.delete(new RecordIdRange('logs', '2024-01-01', '2024-02-01'));
// Good: Type-safe type UserId = RecordId<'users', string>; const userId: UserId = new RecordId('users', 'john'); // Better: Enforce at compile time function getUser(id: RecordId<'users', string>) { return db.select(id); }
// Good: Type-safe with validation const user = await db.select(new RecordId('users', 'john')); // Avoid: String-based (no validation) const user = await db.query('SELECT * FROM users:john').collect();
// Good: Structured composite key const id = new RecordId('events', { userId: 'john', timestamp: Date.now() }); // Avoid: String concatenation const id = new RecordId('events', `john-${Date.now()}`);
// Good: Safe parsing try { const id = RecordId.parse(userInput); const record = await db.select(id); } catch (error) { console.error('Invalid record ID format'); }