Operators filtering (eq, ne, gt, lt, gte, lte, and, or, not, inArray, like, ilike), sorting dengan desc/asc, aggregations (count, sum, avg), group by & having, serta SQL template literals untuk raw SQL yang aman dari SQL injection.

Setelah di episode 5 kita mempelajari operasi CRUD dasar — insert, select, update, delete — pada episode ini kita masuk ke advanced select: filtering dengan berbagai operators, sorting, aggregations, group by, dan SQL template literals untuk raw SQL yang aman.
Query yang kompleks membutuhkan filtering yang tepat, sorting yang benar, dan aggregations untuk analisis data. Drizzle ORM menyediakan semua ini dengan API yang mirip SQL.
import { eq, ne, gt, lt, gte, lte } from 'drizzle-orm'
// eq: sama dengan
await db.select().from(users).where(eq(users.age, 25))
// ne: tidak sama dengan
await db.select().from(users).where(ne(users.role, 'guest'))
// gt, lt, gte, lte: greater than, less than, greater/less or equal
await db.select().from(users).where(gt(users.age, 18))
await db.select().from(users).where(lte(users.age, 65))import { and, or, not } from 'drizzle-orm'
// AND
await db.select().from(users).where(
and(eq(users.isActive, true), gt(users.age, 18))
)
// OR
await db.select().from(users).where(
or(eq(users.role, 'admin'), eq(users.role, 'moderator'))
)
// NOT
await db.select().from(users).where(not(eq(users.isActive, false)))import { inArray, notInArray, like, ilike } from 'drizzle-orm'
// IN
await db.select().from(users).where(
inArray(users.role, ['admin', 'moderator'])
)
// LIKE (case-sensitive)
await db.select().from(users).where(like(users.name, '%John%'))
// ILIKE (case-insensitive)
await db.select().from(users).where(ilike(users.name, '%john%'))import { desc, asc } from 'drizzle-orm'
// Sort by newest first
await db.select().from(users).orderBy(desc(users.createdAt))
// Sort by name alphabetically
await db.select().from(users).orderBy(asc(users.name))
// Multiple sort criteria
await db.select().from(posts)
.orderBy(desc(posts.publishedAt), asc(posts.title))// Page 1: 10 items pertama
await db.select().from(users).limit(10).offset(0)
// Page 2: 10 items berikutnya
await db.select().from(users).limit(10).offset(10)
// Page 3: 10 items berikutnya
await db.select().from(users).limit(10).offset(20)import { count, sum, avg } from 'drizzle-orm'
// Count semua users
const [total] = await db.select({ total: count() }).from(users)
// Count active users
const [activeCount] = await db.select({ total: count() })
.from(users)
.where(eq(users.isActive, true))
// Sum dan avg
const [stats] = await db.select({
totalAge: sum(users.age),
avgAge: avg(users.age),
}).from(users)// Group by role, count per role
await db.select({
role: users.role,
total: count(),
}).from(users).groupBy(users.role)
// Group by dengan having: role dengan lebih dari 5 users
await db.select({
role: users.role,
total: count(),
}).from(users)
.groupBy(users.role)
.having(gte(count(), 5))Untuk query yang sulit di-express dengan query builder:
import { sql } from 'drizzle-orm'
// Raw SQL dengan parameter
const result = await db.execute(
sql`SELECT * FROM users WHERE age > ${25}`
)
// Komposisi query
const conditions = sql`${users.age} > ${18}`
const result = await db.select().from(users).where(
sql`${conditions} AND ${users.isActive} = true`
)Warning
Hindari raw SQL jika bisa di-express dengan query builder. Template literals Drizzle aman dari SQL injection karena menggunakan parameterized queries, tetapi query builder memberikan type safety yang lebih baik.
Pada episode 6 ini, kalian telah memahami Advanced Select:
desc() dan asc() untuk satu atau beberapa kolom.limit() dan offset().count(), sum(), avg().Di episode 7 selanjutnya kita akan mempelajari Relational Queries & Relations Definition — mendefinisikan relasi antar tabel (one-to-many, many-to-one) dan melakukan nested queries. Sampai jumpa di episode 7!