Queries
After opening a database with a schema, every collection exposes a typed query API.
Shipped surface
await db.users.find(); // all rowsawait db.users.find({ role: 'admin' }); // equality filterawait db.users.findOne({ email: 'ali@example.com' }); // first or nullawait db.users.count({ role: 'admin' }); // numberawait db.users.delete({ role: 'user' }); // returns count removed
await db.users.update( { id: '0193…' }, // filter (must match ≤ 1) { role: 'admin' }, // partial patch); // returns count updatedEach method returns its result type inferred from the schema — find() returns Doc[], findOne() returns Doc | null, the mutating methods return number.
The filter is a plain Record<string, unknown> of field-value pairs: every key is interpreted as strict equality against that field. Compound filters narrow with logical AND.
await db.users.find({ role: 'admin', active: true }); // role='admin' AND active=trueIndexed fields (declared with .index(...) / .uniqueIndex(...) in the schema) are looked up via the secondary index. Non-indexed filters fall back to a full scan — fine for small collections, expensive at scale; index the fields you query.
Reactive sibling
Every read above has a live counterpart:
const lq = db.users.live({ role: 'admin' });const unsub = lq.subscribe((users) => render(users));// later: unsub(); lq.dispose();See the Reactive guide for the full subscription model (subscribe, for await, React’s useLive).
Transactions
Multi-document writes commit atomically:
await db.transaction(async (tx) => { await tx.users.insert({ email: 'ali@example.com', role: 'admin' }); await tx.posts.insert({ authorId: '0193…', title: 'Hi' });}); // commit on return, rollback on throwInside the callback, tx.users is a transaction-scoped proxy with the same surface as db.users (insert, find, findOne, count, delete). Throw to roll back; return to commit. Nested db.transaction(...) calls are rejected.
Not yet shipped
The following are on the roadmap (post-v0.x) and not callable today — listed here so you don’t reach for them and find a TypeError:
- Comparison operators (
$gt,$gte,$lt,$lte,$ne,$in,$nin,$exists,$regex). For now: pull the rows with an equality filter and narrow in JS, or add an index and use multiplecount/findOnecalls. - Fluent builder (
.where(...).orderBy(...).limit(...)). For now: filter via the equality-object form and sort/slice the array client-side. - Aggregations (
groupBy,sum,avg). For now: stream rows withlive({...})and aggregate in JS, or — if your dataset outgrows that — this is a sign you want SQLite, not NookDB.
When these land they’ll be in the changelog. The shipped surface above is stable across v0.x.