过滤:where 与操作符全集
本教程共 54 篇 · 第 22 篇 · 更新于 2026-08-11 · 约 4 分钟阅读
本节目标:掌握 where 的全部操作符,学会组合条件、过滤关系与 JSON 字段。
第 19 章已经会用 where: { published: true } 做简单过滤。真实业务的条件复杂得多:范围、模糊、多条件组合、按关系过滤。这一章把操作符全集过一遍。
等值与简写
字段精确匹配有两种写法:
// 简写
await prisma.post.findMany({ where: { status: "PUBLISHED" } });
// 完整写法
await prisma.post.findMany({
where: { status: { equals: "PUBLISHED" } },
});
简写内部就是 equals,两者完全等价。不想要某个值,用 not;但注意 not 不会返回该字段为 null 的记录,需要 null 时补一个 OR:
await prisma.user.findMany({
where: {
OR: [{ name: { not: "Eleanor" } }, { name: null }],
},
});
列表与范围
值在不在一个集合里,用 in / notIn:
await prisma.user.findMany({
where: { role: { in: ["ADMIN", "EDITOR"] } },
});
数值与日期的大小比较用 lt / lte / gt / gte,分别对应小于、小于等于、大于、大于等于:
await prisma.post.findMany({
where: { likes: { gte: 100, lt: 1000 } },
});
日期直接传 Date 对象:
where: { createdAt: { gte: new Date("2026-01-01") } },
字符串匹配
contains 是子串匹配,startsWith、endsWith 管前缀后缀:
await prisma.user.findMany({
where: { email: { endsWith: "prisma.io" } },
});
大小写不敏感加 mode:
await prisma.post.findMany({
where: { title: { contains: "prisma", mode: "insensitive" } },
});
Note
mode: "insensitive"只在 PostgreSQL 连接器上可用(MongoDB 也支持,但 v7 不支持 MongoDB,相关用法留 v6.19)。MySQL 靠数据库排序规则(collation)决定,SQLite 支持有限。
TipstartsWith 能走普通索引,contains 相当于
%关键词%,用不上索引,表大了会慢。前缀搜索优先用 startsWith。
组合:AND / OR / NOT
同层的多个条件默认是 AND 关系,不用显式写。需要括号语义时再用操作符:
await prisma.post.findMany({
where: {
OR: [
{ title: { contains: "Prisma" } },
{ title: { contains: "数据库" } },
],
NOT: { title: { contains: "SQL" } },
published: true,
},
});
AND 里的条件也可以写成数组,适合程序动态拼接过滤条件。
关系过滤
按关联数据过滤是 Prisma 的强项。一对多关系有三个操作符:
await prisma.user.findMany({
where: {
posts: {
some: { published: true }, // 至少一篇已发布
every: { likes: { lte: 50 } }, // 所有帖子点赞都不超过 50
none: { views: { gt: 100 } }, // 没有帖子超过 100 次浏览
},
},
});
some 表示至少一条相关记录满足,none 表示一条都不满足,every 表示全部满足。注意 every 对没有帖子的用户也成立(空集满足所有条件),跟业务直觉可能相反。
一对多关系还可以传空对象判断有无:
// 至少有一篇帖子的用户
where: { posts: { some: {} } },
// 一篇帖子都没有的用户
where: { posts: { none: {} } },
一对一关系用 is / isNot,判断关系不存在直接传 null:
await prisma.post.findMany({
where: {
author: { isNot: { name: "Bob" }, is: { age: { gt: 40 } } },
},
});
JSON 字段过滤
JSON 字段用 path 定位路径再比较。PostgreSQL 的 path 是数组,MySQL 是字符串:
// PostgreSQL
await prisma.user.findMany({
where: {
settings: {
path: ["notifications", "email"],
equals: true,
},
},
});
字符串与数组还有专门操作符:
// PG:settings.favorites.tags 数组包含 "prisma"
where: {
settings: {
path: ["favorites", "tags"],
array_contains: ["prisma"],
},
},
NotePostgreSQL 的 JSON 过滤区分大小写,不支持 mode;且无法按「数组里对象的某个键」过滤(如
treats[*].name),这类查询只有 MySQL 支持。两种数据库的 path 写法不同(数组 vs$.a.b),跨库移植要留意。
参考来源
- Prisma 官方文档:Filtering and sorting
- Prisma 官方文档:Prisma Client API reference(Filter conditions and operators / Json filters)
- Mapagam:Filtering Query Results
- DevSheets:Advanced Querying & Filtering