Query Builder
Arkormˣ query builder is fluent, typed, and delegate-backed.
For multi-step write flows that need atomic commit/rollback behavior, see Transactions.
Common reads
ts
await User.query().get();
await User.query().first();
await User.query().firstOrFail();
await User.query().find(1);Filtering
ts
await User.query()
.whereKey('isActive', true)
.orWhere({ role: 'admin' })
.whereNotNull('email')
.whereIn('id', [1, 2, 3])
.get();Date and range helpers
ts
await User.query().whereBetween('id', [10, 100]).get();
await User.query().whereDate('createdAt', '2026-03-01').get();
await User.query().whereMonth('createdAt', 3, 2026).get();
await User.query().whereYear('createdAt', 2026).get();Ordering and pagination helpers
ts
await User.query().latest().limit(10).get();
await User.query().oldest('updatedAt').offset(20).take(10).get();
await User.query().forPage(2, 15).get();Existence and aggregates
ts
await User.query().exists();
await User.query().doesntExist();
await User.query().count();
await User.query().sum('score');
await User.query().avg('score');Utility helpers
ts
await User.query().pluck('email');
await User.query().value('email');
await User.query().valueOrFail('email');Write helpers (insert/update/upsert)
ts
await User.query().insert({
id: 3,
name: 'Alice',
email: 'alice@example.com',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
});
await User.query().insert([
{
id: 4,
name: 'Bob',
email: 'bob@example.com',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: 5,
name: 'Carol',
email: 'carol@example.com',
isActive: false,
createdAt: new Date(),
updatedAt: new Date(),
},
]);
await User.query().insertOrIgnore([
{
id: 6,
name: 'Dylan',
email: 'dylan@example.com',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
},
]);
const id = await User.query().insertGetId({
id: 7,
name: 'Eve',
email: 'eve@example.com',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
});
await User.query().insertUsing(
['id', 'name', 'email', 'isActive', 'createdAt', 'updatedAt'],
async () => [
{
id: 8,
name: 'Frank',
email: 'frank@example.com',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
},
],
);
await User.query().insertOrIgnoreUsing(
['id', 'name', 'email', 'isActive', 'createdAt', 'updatedAt'],
[
{
id: 9,
name: 'Grace',
email: 'grace@example.com',
isActive: false,
createdAt: new Date(),
updatedAt: new Date(),
},
],
);
await User.query()
.where({ email: 'jane@example.com' })
.updateFrom({ name: 'Jane Updated' });
await User.query().updateOrInsert(
{ email: 'new-user@example.com' },
{
id: 10,
name: 'New User',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
},
);
await User.query().upsert(
[
{
id: 11,
email: 'jane@example.com',
name: 'Jane Upserted',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
},
],
'email',
['name'],
);insert(values)inserts one or many rows.insertOrIgnore(values)inserts and ignores duplicate/conflict errors when supported.insertGetId(values, sequence?)inserts one row and returns the generated key field (defaults toid).insertUsing(columns, query)andinsertOrIgnoreUsing(columns, query)accept arrays, async resolvers, or query-builder sources.updateFrom(values)performs constrained updates and returns affected count when supported by the adapter.updateOrInsert(attributes, values)updates the matching record or inserts a new one.upsert(values, uniqueBy, update?)processes batch upserts keyed by one or many unique columns.
Conditional composition
ts
await User.query()
.when(filters.active, (q) => q.whereKey('isActive', true))
.unless(filters.includeGuests, (q) => q.whereNot({ role: 'guest' }))
.get();