Database
Queries
Query patterns with Drizzle ORM
Drizzle provides two query APIs: the SQL-like query builder and the relational query API.
Basic Queries
Select all
import { , } from "@repo/db"
const = await .select().from()Select with columns
const = await
.select({
: .id,
: .email
})
.from()Where clause
import { , } from "@repo/db"
import { , , , , } from "drizzle-orm"
// Simple equality
const = await
.select()
.from()
.where((.email, "[email protected]"))
// Multiple conditions
const = await
.select()
.from()
.where(
(
(.role, "admin"),
(.emailVerified, true)
)
)
// Pattern matching
const = await
.select()
.from()
.where((.email, "%@gmail.com"))Order and limit
const = await
.select()
.from()
.orderBy((.createdAt))
.limit(10)Relational Queries
Use the relational API for nested data:
// Get user with their team memberships
const = await .query.users.findFirst({
: (.id, ),
: {
: {
: {
: true
}
}
}
})Find many with relations
const = await .query.teams.findMany({
: {
: {
: {
: {
: {
: true,
: true,
: true
}
}
}
}
}
})Insert
Single insert
const [] = await
.insert()
.values({
: .(),
: "[email protected]",
: "New User"
})
.returning()Bulk insert
await .insert().values([
{ : "1", : "First Post", : },
{ : "2", : "Second Post", : }
])Insert with conflict handling
await
.insert()
.values({ , , })
.onConflictDoUpdate({
: .email,
: { , : new () }
})Update
await
.update()
.set({
: "Updated Name",
: new ()
})
.where((.id, ))Update and return
const [] = await
.update()
.set({ : true })
.where((.id, ))
.returning()Delete
await
.delete()
.where((.userId, ))Soft delete pattern
// Add deletedAt to schema
export const = ("Post", {
// ...
: ("deletedAt", { : "date" })
})
// Soft delete
await
.()
.({ : new () })
.((.id, ))
// Query non-deleted only
const = await
.()
.()
.((.deletedAt))Joins
Inner join
const = await
.select({
: ,
:
})
.from()
.innerJoin(, (.authorId, .id))Left join
const = await
.select()
.from()
.leftJoin(, (.id, .authorId))Aggregations
import { , , } from "@repo/db"
import { , , } from "drizzle-orm"
// Count
const [{ }] = await
.select({ : () })
.from()
// Group by
const = await
.select({
: .authorId,
: ()
})
.from()
.groupBy(.authorId)Transactions
await .transaction(async () => {
const [] = await
.insert()
.values({ : , : "New Team", : "new-team" })
.returning()
await .insert().values({
: .id,
: ,
: "owner"
})
})Raw SQL
For complex queries:
import { } from "@repo/db"
import { } from "drizzle-orm"
const = await .execute(`
SELECT * FROM "User"
WHERE "createdAt" > NOW() - INTERVAL '7 days'
`)Type-Safe Patterns
Query wrapper functions
import { , , type User } from "@repo/db"
import { } from "drizzle-orm"
export async function (: string): <User | null> {
const [] = await
.select()
.from()
.where((.id, ))
return ?? null
}
export async function (: string): <User | null> {
const [] = await
.select()
.from()
.where((.email, ))
return ?? null
}In Server Components
import { , } from "@repo/db"
import { } from "@repo/auth/server"
import { } from "drizzle-orm"
export default async function () {
const = await ()
if (!) return null
const [] = await
.select()
.from()
.where((.id, .user.id))
return <>Welcome, {.name}</>
}