From harness-claude
Filters Drizzle ORM queries using eq(), and(), or(), between(), like(), inArray(), isNull(), sql templates, and dynamic conditions. Use for WHERE clauses, boolean logic, and user input-driven filtering.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Filter Drizzle queries with eq(), and(), or(), between(), sql template tag, and custom conditions
Compose type-safe SQL queries with Drizzle's fluent builder for select, insert, update, delete, joins, subqueries, and aggregations in TypeScript.
Provides expertise in Drizzle ORM for TypeScript: schema design, relational queries, Drizzle Kit migrations, and serverless integrations with Neon, Supabase, PlanetScale.
Defines type-safe database schemas, queries, relations, and migrations using Drizzle ORM in TypeScript for PostgreSQL, MySQL, SQLite, Cloudflare D1, and Durable Objects.
Share bugs, ideas, or general feedback.
Filter Drizzle queries with eq(), and(), or(), between(), sql template tag, and custom conditions
eq():import { eq } from 'drizzle-orm';
const admins = await db.select().from(users).where(eq(users.role, 'admin'));
ne, gt, gte, lt, lte:import { gt, lte } from 'drizzle-orm';
const recentPosts = await db
.select()
.from(posts)
.where(gt(posts.createdAt, new Date('2024-01-01')));
and() and or():import { and, or, eq, like } from 'drizzle-orm';
const results = await db
.select()
.from(posts)
.where(
and(
eq(posts.published, true),
or(like(posts.title, `%${search}%`), like(posts.content, `%${search}%`))
)
);
inArray and notInArray:import { inArray } from 'drizzle-orm';
const tagged = await db
.select()
.from(posts)
.where(inArray(posts.status, ['published', 'featured']));
import { between } from 'drizzle-orm';
const rangePosts = await db
.select()
.from(posts)
.where(between(posts.viewCount, 100, 1000));
isNull and isNotNull:import { isNull, isNotNull } from 'drizzle-orm';
const drafts = await db.select().from(posts).where(isNull(posts.publishedAt));
like and ilike (PostgreSQL):import { ilike } from 'drizzle-orm';
const matches = await db
.select()
.from(users)
.where(ilike(users.name, `%${query}%`));
not:import { not, eq } from 'drizzle-orm';
const nonAdmins = await db
.select()
.from(users)
.where(not(eq(users.role, 'admin')));
import { and, eq, ilike, SQL } from 'drizzle-orm';
function buildFilters(params: SearchParams): SQL | undefined {
const conditions: SQL[] = [];
if (params.search) {
conditions.push(ilike(posts.title, `%${params.search}%`));
}
if (params.authorId) {
conditions.push(eq(posts.authorId, params.authorId));
}
if (params.published !== undefined) {
conditions.push(eq(posts.published, params.published));
}
return conditions.length ? and(...conditions) : undefined;
}
const results = await db.select().from(posts).where(buildFilters(params));
sql template tag:import { sql } from 'drizzle-orm';
const results = await db
.select()
.from(posts)
.where(sql`${posts.title} @@ plainto_tsquery('english', ${query})`);
Drizzle filter operators are imported from drizzle-orm and return SQL objects that compose into WHERE clauses. The design mirrors SQL syntax, making it easy to translate SQL knowledge to Drizzle code.
Operator reference:
eq, negt, gte, lt, lteinArray, notInArraybetween, notBetweenisNull, isNotNulllike, ilike, notLike, notIlikeand, or, notexists, notExists (for subqueries)Relational query API filters: The relational API uses a different syntax:
const users = await db.query.users.findMany({
where: (users, { eq, and }) => and(eq(users.role, 'admin'), eq(users.isActive, true)),
});
Type safety: Operators enforce column types at compile time. eq(users.email, 42) is a TypeScript error because email is a text column.
Trade-offs:
ilike is PostgreSQL-specific — use like with manual lowercasing for MySQL compatibilityand() and or() accept undefined values and filter them out, which makes dynamic filter building cleansql template tag bypasses type checking — use it sparingly and validate inputshttps://orm.drizzle.team/docs/operators