Query Builder
Build complex queries with a fluent, chainable API. The QueryBuilder provides a database-agnostic interface for constructing SQL queries programmatically.
Basic Usage
examples/basic-query.ts
const userRepo = orm.getRepository(User);
// Find all usersconst allUsers = await userRepo.find().execute(orm.client);
// Select specific columnsconst users = await userRepo .find() .select("id", "name", "email") .where("isActive = ?", true) .orderBy("createdAt", "DESC") .limit(10) .execute(orm.client);Where Clauses
examples/where-clauses.ts
// Basic WHERE (AND)const active = await userRepo .find() .where("age > ?", 18) .where("isActive = ?", true) .execute(orm.client);
// OR conditionsconst admins = await userRepo .find() .where("role = ?", "admin") .orWhere("role = ?", "superadmin") .execute(orm.client);
// IN clauseconst selected = await userRepo .find() .whereIn("id", [1, 2, 3]) .execute(orm.client);
// NOT INconst excluded = await userRepo .find() .whereNotIn("status", ["banned", "deleted"]) .execute(orm.client);
// BETWEENconst ageRange = await userRepo .find() .whereBetween("age", 18, 35) .execute(orm.client);
// LIKEconst searchResults = await userRepo .find() .whereLike("name", "%john%") .execute(orm.client);
// NULL checksconst noEmail = await userRepo .find() .whereNull("email") .execute(orm.client);
const hasEmail = await userRepo .find() .whereNotNull("email") .execute(orm.client);Joins
examples/joins.ts
// Inner joinconst results = await userRepo .find() .innerJoin("posts", "users.id = posts.authorId") .select("users.name", "posts.title") .execute(orm.client);
// Left join with aggregationconst userPostCounts = await userRepo .find() .leftJoin("posts", "users.id = posts.authorId") .select("users.name", "COUNT(posts.id) as postCount") .groupBy("users.id", "users.name") .execute(orm.client);Ordering, Limiting & Pagination
examples/pagination.ts
// Limit and offsetconst page2 = await userRepo .find() .orderBy("createdAt", "DESC") .limit(10) .offset(10) .execute(orm.client);
// Built-in paginationconst page = await userRepo.paginate(1, 20);// Returns: { data: [...], total: N, page: 1, pageSize: 20 }
// Cursor-based paginationconst page1 = await userRepo.findMany({ take: 10, orderBy: { field: "id", direction: "ASC" },});
const lastId = page1[page1.length - 1]?.id;const page2 = await userRepo.findMany({ cursor: { field: "id", value: lastId, direction: "forward" }, take: 10, orderBy: { field: "id", direction: "ASC" },});Aggregations
examples/aggregations.ts
// Countconst total = await userRepo.count();const activeCount = await userRepo.count({ isActive: true });
// Check existenceconst exists = await userRepo.exists({ email: "alice@example.com" });
// Aggregate functionsconst stats = await userRepo.aggregate({ count: "*", avg: ["age"], min: ["age"], max: ["age"],});// Returns: { count_all: 100, avg_age: 28.5, min_age: 18, max_age: 65 }
// Distinct countconst distinctAges = await userRepo.countDistinct("age");
// Pluck single columnconst emails = await userRepo.pluck("email");Scopes
Apply reusable query fragments defined on your model:
examples/scopes.ts
const activeUsers = await userRepo .scope("active") .limit(10) .execute(orm.client);
// Chain multiple scopesconst activeAdmins = await userRepo .scope("active") .scope("byRole", "admin") .execute(orm.client);Subqueries & EXISTS
examples/subqueries.ts
// WHERE EXISTSconst usersWithPosts = await userRepo .find() .whereExists("SELECT 1 FROM posts WHERE posts.authorId = users.id") .execute(orm.client);
// WHERE NOT EXISTSconst usersWithoutPosts = await userRepo .find() .whereNotExists("SELECT 1 FROM posts WHERE posts.authorId = users.id") .execute(orm.client);Unions & Locking
examples/unions-locks.ts
// UNIONconst allNames = await userRepo .find() .select("name") .union(adminRepo.find().select("name")) .execute(orm.client);
// Pessimistic lockingconst lockedUser = await userRepo .find() .where("id = ?", 1) .forUpdate() .execute(orm.client);Build Without Executing
examples/build.ts
const qb = userRepo .find() .select("id", "email") .where("isActive = ?", true) .orderBy("createdAt", "DESC") .limit(5);
const { query, params } = qb.build();// query: SELECT id, email FROM users WHERE users.deletedAt IS NULL AND isActive = ? ORDER BY createdAt DESC LIMIT 5// params: [true]