跳到主要内容

过滤与排序

Prisma Client 支持使用 where 查询选项进行过滤,以及使用 orderBy 查询选项进行排序

过滤

Prisma Client 允许你根据模型字段的任意组合进行记录过滤,包括相关模型,并支持多种过滤条件

警告

某些过滤条件使用 SQL 运算符 LIKEILIKE,这可能导致你的查询出现意外行为。请参阅我们的过滤常见问题以获取更多信息。

以下查询

  • 返回所有满足以下条件的 User 记录:
    • 邮箱地址以 prisma.io 结尾
    • 至少有一篇已发布的文章(关系查询)
  • 返回所有 User 字段
  • 包含所有 published 等于 true 的相关 Post 记录
const result = await prisma.user.findMany({
where: {
email: {
endsWith: 'prisma.io',
},
posts: {
some: {
published: true,
},
},
},
include: {
posts: {
where: {
published: true,
},
},
},
})
显示CLI结果

过滤条件与运算符

请参阅 Prisma Client 的参考文档,以获取完整的运算符列表,例如 startsWithcontains

组合运算符

你可以使用运算符(如NOTOR)来组合条件进行过滤。以下查询返回所有邮箱以gmail.comcompany.com结尾,但排除了以admin.company.com结尾的邮箱的用户。

const result = await prisma.user.findMany({
where: {
OR: [
{
email: {
endsWith: 'gmail.com',
},
},
{ email: { endsWith: 'company.com' } },
],
NOT: {
email: {
endsWith: 'admin.company.com',
},
},
},
select: {
email: true,
},
})
显示CLI结果

过滤空字段

以下查询返回所有 content 字段为 null 的文章

const posts = await prisma.post.findMany({
where: {
content: null,
},
})

过滤非空字段

以下查询返回所有 content 字段null 的文章

const posts = await prisma.post.findMany({
where: {
content: { not: null },
},
})

根据关系过滤

Prisma Client 支持根据相关记录进行过滤。例如,在以下 schema 中,一个用户可以有多个博客文章

model User {
id Int @id @default(autoincrement())
name String?
email String @unique
posts Post[] // User can have many posts
}

model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
author User @relation(fields: [authorId], references: [id])
authorId Int
}

UserPost 之间的一对多关系允许你根据用户的文章查询用户——例如,以下查询返回所有至少有一篇文章 (some) 浏览量超过 10 次的用户

const result = await prisma.user.findMany({
where: {
posts: {
some: {
views: {
gt: 10,
},
},
},
},
})

你也可以根据作者的属性查询文章。例如,以下查询返回所有作者的 email 包含 "prisma.io" 的文章。

const res = await prisma.post.findMany({
where: {
author: {
email: {
contains: 'prisma.io',
},
},
},
})

过滤标量列表/数组

标量列表(例如,String[])有一组特殊的过滤条件——例如,以下查询返回所有 tags 数组包含 databases 的文章

const posts = await client.post.findMany({
where: {
tags: {
has: 'databases',
},
},
})

不区分大小写的过滤

不区分大小写的过滤作为 PostgreSQL 和 MongoDB 提供商的一项功能提供。MySQL、MariaDB 和 Microsoft SQL Server 默认不区分大小写,因此不需要 Prisma Client 功能即可实现不区分大小写的过滤。

要使用不区分大小写的过滤,请为特定过滤器添加 mode 属性并指定 insensitive

const users = await prisma.user.findMany({
where: {
email: {
endsWith: 'prisma.io',
mode: 'insensitive', // Default value: default
},
name: {
equals: 'Archibald', // Default mode
},
},
})

另请参阅:大小写敏感性

过滤常见问题

过滤在数据库层面如何工作?

对于 MySQL 和 PostgreSQL,Prisma Client 利用 LIKE(和 ILIKE)运算符来搜索给定模式。这些运算符使用 LIKE 特有的符号进行内置模式匹配。模式匹配符号包括 % 用于零个或多个字符(类似于其他正则表达式实现中的 *)和 _ 用于单个字符(类似于 .)。

要匹配字面字符 %_,请确保转义这些字符。例如

const users = await prisma.user.findMany({
where: {
name: {
startsWith: '_benny',
},
},
})

上述查询将匹配任何名称以一个字符后跟 benny 开头的用户,例如 7benny&benny。如果你想查找名称以字面字符串 _benny 开头的用户,你可以这样做:

const users = await prisma.user.findMany({
where: {
name: {
startsWith: '\\_benny', // note that the `_` character is escaped, preceding `\` with `\` when included in a string
},
},
})

排序

使用orderBy根据特定字段或字段集对记录列表或嵌套记录列表进行排序。例如,以下查询返回所有按rolename排序的User记录,并且每个用户的文章按title排序

const usersWithPosts = await prisma.user.findMany({
orderBy: [
{
role: 'desc',
},
{
name: 'desc',
},
],
include: {
posts: {
orderBy: {
title: 'desc',
},
select: {
title: true,
},
},
},
})
显示CLI结果

注意:你也可以对嵌套记录列表进行排序以通过 ID 检索单个记录。

按关系排序

你也可以根据关系属性进行排序。例如,以下查询按作者的电子邮件地址对所有帖子进行排序

const posts = await prisma.post.findMany({
orderBy: {
author: {
email: 'asc',
},
},
})

按关系聚合值排序

2.19.0 及更高版本中,你可以按相关记录的数量进行排序。

例如,以下查询按相关帖子的数量对用户进行排序

const getActiveUsers = await prisma.user.findMany({
take: 10,
orderBy: {
posts: {
_count: 'desc',
},
},
})

注意:目前尚无法返回关系的数量

按相关性排序(PostgreSQL 和 MySQL)

对于 PostgreSQL 的 3.5.0+ 版本和 MySQL 的 3.8.0+ 版本,你可以使用 _relevance 关键字根据查询的相关性对记录进行排序。这利用了全文搜索功能的相关性排名函数。

此功能在PostgreSQL 文档MySQL 文档中进一步解释。

对于 PostgreSQL,你需要通过 fullTextSearchPostgres 预览功能启用按相关性排序。

generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearchPostgres"]
}

按相关性排序可以单独使用,也可以与 search 过滤器一起使用:_relevance 用于对列表进行排序,而 search 则过滤未排序的列表。

例如,以下查询使用 _relevancebio 字段中按术语 developer 过滤,然后按相关性降序对结果进行排序

const getUsersByRelevance = await prisma.user.findMany({
take: 10,
orderBy: {
_relevance: {
fields: ['bio'],
search: 'developer',
sort: 'desc',
},
},
})

注意

在 Prisma ORM 5.16.0 之前,启用 fullTextSearch 预览功能会把 <Model>OrderByWithRelationInput TypeScript 类型重命名为 <Model>OrderByWithRelationAndSearchRelevanceInput。如果你正在使用预览功能,你需要更新你的类型导入。

将空记录排在最前或最后

信息

备注

  • 此功能在 4.16.0 及更高版本中普遍可用。要在 4.1.04.15.0 版本中使用此功能,需要启用 预览功能 orderByNulls
  • 此功能不适用于 MongoDB。
  • 你只能对可选的标量字段进行空值排序。如果你尝试对必填或关系字段进行空值排序,Prisma Client 会抛出 P2009 错误

你可以对结果进行排序,使包含 null 字段的记录出现在最前面或最后面。

如果 name 是一个可选字段,那么以下使用 last 的查询将按 name 排序用户,将 null 记录放在末尾

const users = await prisma.user.findMany({
orderBy: {
updatedAt: { sort: 'asc', nulls: 'last' },
},
})

如果你希望 null 值记录出现在返回数组的开头,请使用 first

const users = await prisma.user.findMany({
orderBy: {
updatedAt: { sort: 'asc', nulls: 'first' },
},
})

请注意,first 也是默认值,因此如果你省略 null 选项,null 值将首先出现在返回数组中。

排序常见问题

我可以执行不区分大小写的排序吗?

关注 GitHub 上的 issue #841

© . All rights reserved.