Update & Delete
Modify existing records with partial updates, or remove them — one at a time or in bulk.
Update a record
Updates are partial — only the fields you provide are changed. Existing fields not included in the update are preserved.
final updated = await Koolbase.db
.doc('record-uuid-here')
.update({
'title': 'Updated title',
'published': true,
});
// Only 'title' and 'published' changed
// All other fields remain unchanged
print(updated.data['title']); // Updated title
print(updated.data['body']); // original body still here
print(updated.updatedAt); // new timestampPartial updates
null explicitly. There is no unset operation — the JSONB data column is merged on update.Upsert: update or insert
Insert a record, or update the existing one that matches a filter — in a single call. The server decides the outcome: exactly one match updates that record, no match inserts a new one (seeded with the match fields), and more than one match is an error.
final result = await Koolbase.db.upsert(
collection: 'profiles',
match: {'user_id': userId},
data: {'weight_kg': 70},
);
print(result.created); // true if inserted, false if updated
print(result.record.id);Online-only
insert — it is not queued for offline sync. It throws on network failure rather than risk creating a duplicate. Available in koolbase_flutter 3.1.0+.Delete a record
Permanently removes a record. This action cannot be undone.
await Koolbase.db
.doc('record-uuid-here')
.delete();Bulk delete with deleteWhere
Delete every record matching a filter in a single call. Returns the number of records deleted.
final deleted = await Koolbase.db.deleteWhere(
collection: 'sessions',
filters: {'user_id': userId, 'status': 'expired'},
);
print('Deleted $deleted records');A filter is always required
deleteWhere requires a non-empty filters map. The collection's delete rule still applies: for owner and scoped rules the delete is automatically limited to the calling user's own records.Bulk semantics
Conditional writes
Every record carries a $revision, which the server advances on each write. Pass it back and the write applies only if the record still carries it.
final record = await Koolbase.db.doc(id).get();
// Applies only if nothing has changed the record since we read it
await Koolbase.db.doc(id).update(
{'title': 'Corrected'},
expectedRevision: record.revision,
);Over HTTP, expected_revision goes in the body for an update and as a query parameter for a delete:
PATCH /v1/sdk/db/records/{record_id}
{"data": {"title": "Corrected"}, "expected_revision": 7}
DELETE /v1/sdk/db/records/{record_id}?expected_revision=7If the record has moved on, the write is refused with 409 revision_mismatch — carrying the record as it now stands, so deciding what to do next needs no second request:
{
"code": "revision_mismatch",
"error": "the record has changed since you read it",
"details": {
"expected_revision": 7,
"current_revision": 9,
"record": { "$id": "...", "$revision": 9, "title": "Edited elsewhere" }
}
}Optional, and most apps do not need it
expected_revision behaves as it always has: it applies, whatever the record looked like when you read it. That is fine when one thing writes a record at a time. It becomes a silent lost update when two do — a second device, a Function, a colleague — and neither writer ever learns that one change replaced the other. Reach for this where that matters, not everywhere.The check and the write are one operation on the server, so nothing can slip between them. Fetching a record, comparing it yourself, then writing cannot offer that: another write can land in the gap.
Access rules on write and delete
Write and delete operations are subject to the collection's rules. The three possible values:
authenticatedAny logged-in user can update or delete any record
ownerOnly the record's creator (created_by) can update or delete it
Owner check
owner, the server checks that record.created_by == current_user.id. If not, a 403 Forbidden error is returned. Make sure the user is logged in before attempting to update or delete owned records.Error handling
try {
await Koolbase.db.doc(postId).delete();
} on KoolbaseException catch (e) {
switch (e.code) {
case 'not_found':
showError('Post not found');
case 'permission_denied':
showError('You do not have permission to delete this post');
default:
showError('Failed to delete: ${e.message}');
}
}