ctx.db inside a
query or mutation.
There’s no separate client or query language.
bijection/customers.ts
listActive like any other query, and receive new results when
the customers behind the view change.
Reading a single object
Pass the view’s name and an ID from its key table todb.get:
bijection/customers.ts
null when the customer
isn’t a member of the view, for example because it’s archived. The row’s _id
and _creationTime are those of the customers document.
A few details follow from views sharing their key table’s IDs:
- Always name the view. The one-argument form
ctx.db.get(id)reads the table the ID belongs to, which iscustomers, not the view. - An ID of another table is a type error:
ctx.db.get("active_customers", id)requires anId<"customers">. ctx.db.normalizeId("active_customers", value)checks thatvalueis a valid ID of the key table. It doesn’t check that the object is currently in the view; usedb.getfor that.
Querying a view
ctx.db.query works on views with the usual methods for
filtering, ordering
and retrieving results:
usePaginatedQuery on the client:
bijection/customers.ts
Doc<"customer_summaries"> from
./_generated/dataModel is the type of one row.
Indexes on views
Declare indexes on a view with.index, just like a table. The fields must exist in the view’s output:
bijection/schema.ts
withIndex:
Views are read-only
A view’s rows come from its expression, so they can’t be written directly.insert, patch, replace and delete on a view are type errors, and fail at
runtime with a ReadOnlyView error even from internal functions. To change a
view’s rows, change the tables it reads.
Consistency and reactivity
Views follow the same rules as every other read in Bijection:- Consistency. All reads in one function, including every table a view reads, happen at the same snapshot. A view never combines inputs from different moments.
- Reactivity. A query depends on everything the views it reads depend on. When a write changes the result, including a new row that starts to match a filter or a change to a joined table, subscribed clients get the new result.
- Read your writes. Inside a mutation, a view reflects the mutation’s own
earlier writes. If you insert an order and then read
customer_summaries, the new order is counted. If the mutation throws, none of it is visible to anyone. - Conflicts. Mutations that read a view are protected by optimistic concurrency control over the view’s inputs, including rows that would newly match an empty range.
Limits and errors
Reading a view counts toward the ordinary read limits of the function, and toward the view’s own work limits. A view read can fail with these errors:
A failed read returns no partial result. Handle these like other
errors in queries.