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 unchangedThis 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 preservedFull 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
| Operation | Unmentioned Fields | Use Case |
|---|---|---|
| Partial merge | Preserved | Update a few fields |
{ set: ... } | Become NONE | Replace 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.