Cerial
Objects

Updating Objects

Updating embedded object fields — partial merge vs full replacement with the set wrapper.

Cerial supports two modes for updating embedded object fields: partial merge (default) and full replacement with { set: ... }.

All examples use this schema:

object Address {
  street String
  city String
  state String
  zipCode String?
}

model User {
  id Record @id
  name String
  address Address
  shipping Address?
}

Partial Update (Merge)

By default, passing an object in the data field performs a partial merge. Only the specified fields change; all other fields on the object are preserved:

await client.db.User.updateMany({
  where: { id: user.id },
  data: { address: { city: 'Boston' } },
});
// Only `city` is changed
// `street`, `state`, and `zipCode` remain unchanged

This is useful when you want to modify one or two fields without re-specifying the entire object.

Multiple Fields in a Partial Update

await client.db.User.updateMany({
  where: { id: user.id },
  data: {
    address: {
      city: 'Boston',
      state: 'MA',
    },
  },
});
// `city` and `state` are updated
// `street` and `zipCode` are preserved

Full Replacement with set

To replace the entire object, use the { set: ... } wrapper. This discards the existing object and stores the new one in its place:

await client.db.User.updateMany({
  where: { id: user.id },
  data: {
    address: {
      set: { street: '1 Main St', city: 'NYC', state: 'NY' },
    },
  },
});
// Entire address object is replaced
// Any fields not included in `set` become NONE (absent)

The difference between merge and set matters. Partial merge keeps fields you don't mention. set replaces the whole object — any fields not provided in the set value become NONE (absent). Use set when you need a clean slate, and merge when you want to tweak individual fields.

Comparison

OperationUnmentioned FieldsUse Case
Partial mergePreservedUpdate a few fields
{ set: ... }Become NONEReplace the entire object

Side-by-Side Example

Given an existing address { street: '123 Main', city: 'NYC', state: 'NY', zipCode: '10001' }:

// Partial merge — zipCode stays '10001'
await client.db.User.updateMany({
  where: { id: user.id },
  data: { address: { city: 'Boston', state: 'MA' } },
});
// Result: { street: '123 Main', city: 'Boston', state: 'MA', zipCode: '10001' }
// Full replacement — zipCode becomes NONE
await client.db.User.updateMany({
  where: { id: user.id },
  data: {
    address: { set: { street: '456 Elm', city: 'Boston', state: 'MA' } },
  },
});
// Result: { street: '456 Elm', city: 'Boston', state: 'MA' }
// zipCode is absent (NONE)

Removing an Optional Object

For optional object fields, you can remove the object entirely by setting it to undefined:

await client.db.User.updateMany({
  where: { id: user.id },
  data: { shipping: undefined },
});
// user.shipping is now undefined (field absent in SurrealDB)

You can also use the unset parameter instead of passing undefined in data. See Queries for details on the unset option.

On this page