UpsertPromise<T, I, J>

The UpsertPromise class provides a chainable interface for configuring UPSERT operations (insert if not exists, replace if exists). It extends Promise, allowing you to await it directly or chain configuration methods.

Returned by: SurrealQueryable.upsert()

Source: query/upsert.ts

Type Parameters

  • T - The result type

  • I - The input type for record data

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

Configuration Methods

.content()

Set the complete content for the record (insert or replace).

Method Syntax

upsertPromise.content(data)

Parameters

ParameterTypeDescription
data Values<I>Complete record data (excluding id field).

Returns

UpsertPromise<T, I, J> - Chainable promise

Example

const user = await db.upsert(new RecordId('users', 'john'))
.content({
name: 'John Doe',
email: 'john@example.com',
age: 30
});
// Inserts if not exists, replaces entirely if exists

.merge()

Merge data into the record (insert if not exists, merge if exists).

Method Syntax

upsertPromise.merge(data)

Parameters

ParameterTypeDescription
data Partial<Values<I>>Partial data to merge.

Returns

UpsertPromise<T, I, J> - Chainable promise

Example

const user = await db.upsert(new RecordId('users', 'john'))
.merge({
name: 'John Doe',
last_login: DateTime.now()
});
// If exists: merges fields; if not: creates with these fields

.replace()

Replace specific fields.

Method Syntax

upsertPromise.replace(data)

Parameters

ParameterTypeDescription
data Values<I>Fields to replace.

Returns

UpsertPromise<T, I, J> - Chainable promise

.patch()

Apply JSON Patch operations.

Method Syntax

upsertPromise.patch(operations)

Parameters

ParameterTypeDescription
operations PatchOperation[]JSON Patch operations.

Returns

UpsertPromise<T, I, J> - Chainable promise

.where()

Add a WHERE clause for conditional upsert.

Method Syntax

upsertPromise.where(condition)

Parameters

ParameterTypeDescription
condition ExprLikeThe condition expression (string or Expression object).

Returns

UpsertPromise<T, I, J> - Chainable promise

.output()

Specify what to return.

Method Syntax

upsertPromise.output(fields)

Parameters

ParameterTypeDescription
fields Output"NONE", "BEFORE", "AFTER", "DIFF", or field list.

Returns

UpsertPromise<T, I, J> - Chainable promise

.timeout()

Set operation timeout.

Method Syntax

upsertPromise.timeout(duration)

Returns

UpsertPromise<T, I, J> - Chainable promise

.version(), .json(), .stream()

See other query builders for these common methods.

Complete Examples

Basic Upsert

import { Surreal, RecordId } from 'surrealdb';

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

// Upsert: insert if not exists, replace if exists
const user = await db.upsert(new RecordId('users', 'john'))
.content({
name: 'John Doe',
email: 'john@example.com',
role: 'user'
});

Upsert with Merge

// Safer: merge instead of replace
const user = await db.upsert(new RecordId('users', 'john'))
.merge({
last_login: DateTime.now(),
login_count: 1
});
// If user exists: only updates these fields
// If not: creates user with these fields

Bulk Upsert

const users = await db.upsert(new Table('users'))
.content(userDataArray);

Track Changes

const result = await db.upsert(new RecordId('users', 'john'))
.content(userData)
.output('DIFF');

if (result) {
console.log('Created or updated:', result);
}

Conditional Upsert

const user = await db.upsert(new RecordId('users', 'john'))
.merge({ status: 'active' })
.where('verified = true');

UPSERT vs CREATE vs UPDATE

// CREATE: Fails if record exists
try {
await db.create(recordId).content(data);
} catch (error) {
// Error if exists
}

// UPDATE: Fails if record doesn't exist
try {
await db.update(recordId).merge(data);
} catch (error) {
// Error if not found
}

// UPSERT: Works in both cases
await db.upsert(recordId).content(data);
// Always succeeds

Use Cases

Session Management

// Update session or create new one
async function updateSession(sessionId: string, data: SessionData) {
return db.upsert(new RecordId('sessions', sessionId))
.merge({
...data,
last_activity: DateTime.now()
});
}

Cache Pattern

// Write-through cache
async function cacheSet(key: string, value: unknown) {
return db.upsert(new RecordId('cache', key))
.content({
value,
expires_at: DateTime.now().plus(Duration.parse('1h'))
});
}

Counter Pattern

// Increment counter or initialize
const counter = await db.upsert(new RecordId('counters', 'page_views'))
.merge({
count: 1,
last_increment: DateTime.now()
});

Chaining Pattern

const result = await db.upsert(new RecordId('users', 'john'))
.content(userData)
.output('AFTER')
.timeout(Duration.parse('5s'));

See Also