Writing
Writes are Matter commands, made as the member using the app. They show at once in every read on this computer, and resolve when the server accepts them.
const deals = matter.table('Deals')
const id = await deals.insert({ title: 'Acme', values: { Stage: 'Lead', Owner: '$viewer' } })await deals.update(id, { Stage: 'Won' }, { if: { Stage: 'Lead' } })await deals.upsert('by_email', [{ values: { Email: 'sam@acme.com', Stage: 'Lead' } }])await deals.delete(id)| Write | What it does |
|---|---|
insert(row) or insert(rows) |
Creates rows. Resolves to the new row’s id, or a list of ids. |
update(id, values, { title?, if? }) |
Changes the values you give, and the title if you give one. |
updateMany([{ id, title?, values?, if? }]) |
Several updates at once. |
upsert(on, rows) |
Matches each row on a unique index: updates the rows it matches and creates the rest. Resolves to their ids. |
delete(id) or delete(ids) |
Deletes rows. |
A row to insert or upsert is { title?, values }. Each write takes at most 500 rows at a time. Every write but delete also takes { createOptions: true } (see Options).
The title is the row’s name: the table’s title field, Name say. Give it as title, as here, or in values by the field’s name; reads give it as both row.title and row.values.Name.
Values
Section titled “Values”Values use names, the same as reads:
- options by name: see Options.
- people by id or name, or
'$viewer'for the member writing. - linked rows by id or title.
- dates as
YYYY-MM-DD. nullclears a value.
A field that holds one person or linked row takes it alone, or as a list of one.
Options
Section titled “Options”A write names options the field has. Naming one it doesn’t have fails with invalid, listing the field’s options, so a typo or an option renamed in Matter doesn’t quietly grow the field. To add the options a write names, say so:
await deals.update(id, { Stage: 'Churned' }, { createOptions: true })await tags.insert([{ values: { Labels: ['urgent', 'new'] } }], { createOptions: true })await matter.batch(ops, { createOptions: true }) // or createOptions on one opWith typed tables, a write’s option names are checked against the field’s, unless it passes createOptions: true.
Claiming work with if
Section titled “Claiming work with if”update with if applies only when the row still holds those values. Otherwise it fails with precondition_failed, and nothing changes. Use it so two runs can’t take the same work:
try { await actions.update(id, { Status: 'sending' }, { if: { Status: 'approved' } })} catch (error) { if (error.code === 'precondition_failed') return // someone else took it throw error}Upsert
Section titled “Upsert”upsert(on, rows) matches on a unique index, by its name, or on a field that has a unique index of its own:
await people.upsert('by_email', [ { title: 'Sam Lee', values: { Email: 'sam@acme.com', Company: 'Acme' } }, { title: 'Ana Ruiz', values: { Email: 'ana@initech.com', Company: 'Initech' } },])A write that would give a unique index a second row with the same values fails with conflict.
Batches
Section titled “Batches”matter.batch(ops) runs several writes in order. It isn’t atomic: a failure stops the batch, and the writes before it stay.
await matter.batch([ { table: 'Deals', op: 'update', rows: [{ id, values: { Stage: 'Won' } }] }, { table: 'Activity', op: 'insert', rows: [{ title: 'Won Acme', values: { Deal: id } }] },])Each op is insert, update or upsert with rows (and on for upsert), or delete with ids.
Offline
Section titled “Offline”When the computer is offline, or the server doesn’t answer, a write resolves after 20 seconds anyway: update, updateMany and delete resolve { pending: true }, and insert and upsert resolve to the new ids. The write is already in every read on this computer, and it lands once the computer reconnects.