RelatePromise<T, J>

The RelatePromise class provides a chainable interface for configuring RELATE operations to create graph relationships (edges) between records. It extends Promise, allowing you to await it directly or chain configuration methods.

Returned by: SurrealQueryable.relate()

Source: query/relate.ts

Type Parameters

  • T - The result type (edge record type)

  • J - Boolean indicating if result is JSON (default: false)

Configuration Methods

.unique()

Enforce a unique relationship constraint (only one edge between the same nodes).

Method Syntax

relatePromise.unique()

Returns

RelatePromise<T, J> - Chainable promise

Example

// Only allow one 'likes' edge between user and post
const edge = await db.relate(
new RecordId('users', 'john'),
new Table('likes'),
new RecordId('posts', '1')
).unique();
// If edge already exists, this won't create a duplicate

.output()

Specify what to return from the operation.

Method Syntax

relatePromise.output(fields)

Parameters

ParameterTypeDescription
fields Output"NONE", "AFTER", or specific field list.

Returns

RelatePromise<T, J> - Chainable promise

Example

const edge = await db.relate(
new RecordId('users', 'john'),
new Table('follows'),
new RecordId('users', 'jane')
).output('id', 'in', 'out', 'created_at');

.timeout()

Set a timeout for the operation.

Method Syntax

relatePromise.timeout(duration)

Parameters

ParameterTypeDescription
duration DurationMaximum time to wait.

Returns

RelatePromise<T, J> - Chainable promise

.version()

Create the relationship at a specific version.

Method Syntax

relatePromise.version(timestamp)

Parameters

ParameterTypeDescription
timestamp DateTimeThe version timestamp.

Returns

RelatePromise<T, J> - Chainable promise

.json()

Return result as JSON string.

Method Syntax

relatePromise.json()

Returns

RelatePromise<T, true> - Promise returning JSON string

.stream()

Stream results as relationships are created.

Method Syntax

relatePromise.stream()

Returns

AsyncIterableIterator - Async iterator

Complete Examples

Basic Relationship

import { Surreal, RecordId, Table, DateTime } from 'surrealdb';

const db = new Surreal();
await db.connect('ws://localhost:8000');

// Create a single relationship
const edge = await db.relate(
new RecordId('users', 'john'),
new Table('likes'),
new RecordId('posts', '1'),
{ created_at: DateTime.now() }
);

console.log('Edge created:', edge.id);
console.log('From:', edge.in); // users:john
console.log('To:', edge.out); // posts:1

Multiple Relationships

// Create multiple edges at once
const edges = await db.relate(
[new RecordId('users', 'john'), new RecordId('users', 'jane')],
new Table('follows'),
[new RecordId('users', 'alice'), new RecordId('users', 'bob')]
);

// Creates 4 edges:
// john->follows->alice
// john->follows->bob
// jane->follows->alice
// jane->follows->bob

Unique Relationships

// Prevent duplicate 'likes'
const edge = await db.relate(
new RecordId('users', 'john'),
new Table('likes'),
new RecordId('posts', '1'),
{ timestamp: DateTime.now() }
).unique();

// Second call won't create duplicate
const duplicate = await db.relate(
new RecordId('users', 'john'),
new Table('likes'),
new RecordId('posts', '1')
).unique();
// Returns existing edge

Relationship with Data

const friendship = await db.relate(
new RecordId('users', 'john'),
new Table('friends'),
new RecordId('users', 'jane'),
{
since: DateTime.parse('2024-01-15'),
strength: 0.8,
mutual: true,
tags: ['colleague', 'neighbor']
}
);

Specific Edge ID

// Use specific ID for the edge
const edge = await db.relate(
new RecordId('users', 'john'),
new RecordId('likes', 'specific-edge-id'),
new RecordId('posts', '1'),
{ strength: 10 }
);

Fan-out Relationships

// One user follows many
const edges = await db.relate(
new RecordId('users', 'john'),
new Table('follows'),
[
new RecordId('users', 'alice'),
new RecordId('users', 'bob'),
new RecordId('users', 'carol')
]
);

console.log(`Created ${edges.length} follow edges`);

Streaming Bulk Relationships

const users = await db.select(new Table('users'));
const popularPost = new RecordId('posts', 'viral-post');

const edges = db.relate(
users.map(u => u.id),
new Table('viewed'),
popularPost,
{ viewed_at: DateTime.now() }
);

for await (const edge of edges.stream()) {
console.log(`Created view edge: ${edge.id}`);
}

Bidirectional Relationships

// Create friendship in both directions
await db.relate(
new RecordId('users', 'john'),
new Table('friends'),
new RecordId('users', 'jane')
);

await db.relate(
new RecordId('users', 'jane'),
new Table('friends'),
new RecordId('users', 'john')
);

Relationship Metadata

const edge = await db.relate(
new RecordId('users', 'john'),
new Table('rated'),
new RecordId('movies', 'inception'),
{
rating: 5,
review: 'Amazing movie!',
watched_at: DateTime.parse('2024-01-15'),
platform: 'Netflix'
}
);

Temporal Relationships

// Track when relationship was created
const edge = await db.relate(
new RecordId('users', 'john'),
new Table('employed_at'),
new RecordId('companies', 'acme'),
{
started_at: DateTime.parse('2024-01-01'),
position: 'Developer',
department: 'Engineering'
}
);

Weighted Graph

// Create weighted edges for graph algorithms
const edge = await db.relate(
new RecordId('cities', 'new-york'),
new Table('connected_to'),
new RecordId('cities', 'boston'),
{
distance: 215, // miles
travel_time: Duration.parse('4h'),
cost: 50
}
);

Delete and Recreate Pattern

// Remove existing relationship and create new one
const userId = new RecordId('users', 'john');
const postId = new RecordId('posts', '1');

// Delete existing edge
await db.query(
surql`DELETE FROM likes WHERE in = ${userId} AND out = ${postId}`
).collect();

// Create new edge with updated data
const edge = await db.relate(
userId,
new Table('likes'),
postId,
{ created_at: DateTime.now() }
);

Graph Traversal Example

// Create relationships
await db.relate(
new RecordId('users', 'john'),
new Table('follows'),
new RecordId('users', 'jane')
);

// Query traversal
const followers = await db.query(
surql`SELECT <-follows<-users.* AS followers FROM users:jane`
).collect();

console.log('Jane has followers:', followers);

Best Practices

1. Use Unique for One-to-One

// Good: Prevent duplicate likes
await db.relate(from, new Table('likes'), to).unique();

// Avoid: Allowing duplicates
await db.relate(from, new Table('likes'), to);
// May create multiple edges

2. Include Metadata

// Good: Track when relationship was created
await db.relate(from, edge, to, {
created_at: DateTime.now(),
source: 'web-app'
});

// Basic: No metadata
await db.relate(from, edge, to);

3. Use Specific Edge IDs for Updates

// Good: Use specific ID to update later
const edgeId = new RecordId('likes', Uuid.v7());
await db.relate(from, edgeId, to, metadata);

// Later: easy to update
await db.update(edgeId).merge({ updated_at: DateTime.now() });

See Also