GraphQL Nexus 是一个代码优先、类型安全的适用于 JavaScript/TypeScript 的 GraphQL Schema 构建库。了解如何使用 Prisma client 和新的 nexus-prisma
插件将其连接到数据库。

回顾:使用 GraphQL Nexus 进行代码优先开发
在上一篇文章中,我们介绍了 GraphQL Nexus,这是一个支持 TypeScript 和 JavaScript 代码优先开发的 GraphQL 库。使用 Nexus,GraphQL schema 是 以编程方式定义和实现的。因此,它遵循了其他语言(如 Scala 的 sangria-graphql
,Python 的 graphlq-ruby
或 graphene
)中成熟的 GraphQL 服务开发方法。
今天的文章是关于如何将基于 Nexus 的 GraphQL 服务连接到数据库,我们将使用 Prisma client 以及新的 nexus-prisma
插件。稍后,我们将引导您通过一个实际例子,从头开始构建一个博客应用的 GraphQL API。
nexus-prisma
支持 PostgreSQL、MySQL 和 MongoDB。在此查找其文档。
TLDR:nexus-prisma
插件的优势
- 为您的 Prisma 模型提供 GraphQL CRUD 操作
- 自定义您的 Prisma 模型,例如 隐藏特定字段 或 添加计算字段
- 完全类型安全:为 GraphQL schema 和数据库提供一致的类型集
- 与 GraphQL 生态系统兼容(例如
apollo-server
、graphql-yoga
、...)
理解 nexus-prisma
工作流程
Prisma client 作为 ORM 替代品
如果您之前没有使用过 Prisma,这里快速介绍一下它的工作原理
- 定义您的 datamodel 或让 Prisma 内省您现有的数据库
- 生成您的 Prisma client,即一个类型安全的数据库客户端
- 在应用程序中(例如 GraphQL API)使用 Prisma client 访问您的数据库
nexus-prisma
插件底层原理
当加入 nexus-prisma
时,还需要一步:调用 nexus-prisma-generate
codegen CLI。它会为您的 Prisma 模型生成完整的 GraphQL CRUD API 构建块,例如 对于 User
模型,它包含
- 查询
user(...): User!
:获取单条记录users(...): [User!]!
:获取记录列表usersConnection(...): UserConnection!
:Relay 连接 & 聚合
- 变更 (Mutations)
createUser(...): User!
:创建新记录updateUser(...): User
:更新记录deleteUser(...): User
:删除记录updatesManyUsers(...): BatchPayload!
:批量更新多条记录deleteManyUsers(...): BatchPayload!
:批量删除多条记录
- GraphQL 输入类型
UserCreateInput
:封装记录的所有字段UserUpdateInput
:封装记录的所有字段UserWhereInput
:为记录的所有字段提供过滤器UserWhereUniqueInput
:为记录的唯一字段提供过滤器UserUpdateManyMutationInput
:封装可以批量更新的字段UserOrderByInput
:按字段指定升序或降序
UserCreateInput
和UserUpdateInput
在处理关联字段的方式上有所不同。
使用 nexus
和 nexus-prisma
编写 GraphQL 服务代码时,您可以在这些操作的基础上,通过公开和自定义它们来满足您自己的 API 需求

生成 CRUD 构建块后,您可以使用 nexus-prisma
中的 prismaObjectType
开始公开(和自定义)它们。以下代码片段展示了一个基于 Prisma 和 nexus-prisma
的 TODO 列表应用 GraphQL API 实现
我们将 prismaObjectType
应用于 Query
和 Mutation
。对于 Query
,我们保留所有字段(即 todo
、 todoes
和 todoesConnection
)。对于 Mutation
,我们使用 prismaFields
来自定义公开的操作。
prismaFields
让我们选择要公开的操作。在这种情况下,我们只想保留用于 创建 模型(createTodo
)的操作。从生成的 CRUD 构建块中,我们既不包含 updateTodo
也不包含 deleteTodo
,而是实现我们自己的 markAsDone(id: ID!)
变更来勾选某个 Todo
。
示例:从标准 CRUD 到定制的 GraphQL API
现在让我们快速浏览一个标准的 Prisma 用例,看看如何通过几个简单的步骤为一个博客应用快速构建 GraphQL API。我们将这样做
- 使用 TypeScript 设置 Prisma 项目(使用免费的演示数据库)
- 定义模型、迁移数据库并生成 Prisma client
- 通过
nexus-prisma
公开完整的 CRUD GraphQL API - 通过
nexus-prisma
定制 GraphQL API
如果您想跟着做,需要安装 Prisma CLI
1) 使用 TypeScript、nexus
和 nexus-prisma
设置 Prisma 项目
本节主要介绍您的项目设置。如果您不想跟着写代码,可以跳过本节,否则请展开下面的部分。
使用 Prisma CLI 创建一个简单的 Prisma 项目
在交互式提示中,选择以下选项
- 选择 Demo server(包含 Prisma Cloud 中的免费托管演示数据库)
- 在浏览器中通过 Prisma Cloud 进行认证(如果需要)
- 回到您的终端,确认所有建议的值
作为 Demo server 的替代方案,您也可以使用 Docker 在本地运行 Prisma。
接下来,您需要配置您的 nexus-prisma
工作流程。添加以下依赖项(在 myblog
目录中)
接下来,将以下两行添加到您的 prisma.yml
的末尾
这确保了无论何时您更改模型,Prisma client 以及生成的 nexus-prisma
CRUD 构建块都会自动更新。
由于我们使用的是 TypeScript,让我们快速添加一个 tsconfig.json
最后,继续添加一个 start
脚本,您将使用它进行开发。它会启动一个开发服务器,在后台监视您的文件,并在您编写代码时更新生成的 SDL 和 Nexus typings。将其添加到您的 package.json
中
2) 定义模型、迁移数据库并生成 Prisma client
prisma init
命令在 datamodel.prisma
中创建了一个默认的 User
模型。由于我们正在构建一个博客应用程序,让我们根据应用程序领域调整模型
接下来,您需要通过将 datamodel 应用于数据库来迁移数据库。使用以下命令,datamodel.prisma
中定义的每个模型都将映射到底层数据库中的一个表
由于您之前在 prisma.yml
中配置了 post-deploy
hook,您的 Prisma client 和 CRUD 构建块会自动更新。
3) 通过 nexus-prisma
公开完整的 CRUD GraphQL API
在项目的早期阶段,API 公开完整的 CRUD 功能通常很有帮助——更严格的 API 需求通常会随着时间的推移而出现。nexus-prisma
通过提供从完整 CRUD 到定制 API 操作的直接路径,完美地考虑了这一点。
让我们从一个公开定义模型的完整 CRUD 功能的 GraphQL API 开始(请注意,这包括过滤器、分页和排序)。创建一个名为 index.ts
的新文件,并将以下代码添加到其中
在这个简短的教程中,我们不太关注文件结构。请查看我们的
graphql-auth
示例,了解适当的设置和模块化的 schema。
运行 npm run start
后,您可以在 http://localhost:4000
上打开您的 GraphQL 服务的 GraphQL Playground。有了您上面编写的少量代码,您就已经拥有了一个功能齐全的 GraphQL CRUD API。
这是如何工作的?nexus-prisma-generate
生成了一个 GraphQL schema,它为 Prisma 模型(您的 CRUD 构建块)提供了一个 CRUD API。这个 GraphQL schema 遵循 OpenCRUD 规范。使用 prismaObjectType
函数,您现在可以公开和自定义该 schema 的操作。
prismaObjectType
和 prismaFields
使用白名单方法,这意味着您需要明确列出要公开的字段。通配符 *
包含所有字段。

4) 通过 nexus-prisma
定制 GraphQL API
在本节中,我们将学习如何定制 来自 nexus-prisma
的 CRUD GraphQL API。具体来说,我们将
- 从
User
模型中隐藏一个字段 - 向
Post
模型添加一个计算字段 - 隐藏
createPost
和updatePost
变更 - 添加两个自定义
createDraft
和publish
变更
4.1) 从 User
模型中隐藏一个字段
在本节中,我们将从 User
模型中隐藏 email
字段。
要定制模型,我们需要将 prismaObjectType
函数应用于它,并将 definition(t)
函数作为选项传递
通过在 模型 t
上调用 prismaFields
,我们可以定制公开的字段(及其参数)。由于 email
不包含在列表中,它将从我们的 GraphQL API 中移除。

要应用更改,您需要明确将 User
传递给 makePrismaSchema
中的 types
数组
请注意,您的编辑器能够根据生成的 CRUD 构建块,建议将什么传递给 prismaObjectType
和 prismaFields
。这意味着当您键入 prismaObjectType('')
并按下 ctrl+space 时,它会建议所有生成的 CRUD 构建块的名称。当调用 t.prismaFields([''])
时,它会建议 t
的字段
4.2) 向 Post
模型添加计算字段
新的代码优先方法 nexus-prisma
也使得向 Prisma 模型添加计算字段变得容易。假设您想向 Post
添加一个字段,该字段始终返回完全大写的 title
。以下是如何实现它
我们使用 来自 graphql-nexus
的 t.string(...)
API 向我们的模型添加一个新字段。因为它是计算字段(因此 nexus-prisma
不能自动解析),我们还需要为其附加一个 resolver。

和之前一样,您需要明确将定制的 Post
模型添加到 types
数组中
4.3) 隐藏 createPost
和 updatePost
变更
就像我们从 User
模型中隐藏 email
字段一样,我们也可以从 Query
/ Mutation
类型中隐藏操作,这些操作是生成的 nexus-prisma
CRUD 构建块的一部分。
要隐藏 createPost
和 updatePost
,我们再次需要将 definition(t)
作为选项传递给 prismaObjectType
。请注意,一旦我们在类型上调用 prismaFields
,我们就需要明确列出所有要保留的字段(空数组将被解释为“不保留任何操作”)
生成的 CRUD GraphQL API 也包括批量和 upsert 操作,为简洁起见,我们也在此排除它们。
4. 添加两个自定义 createDraft
和 publish
变更
最后,我们向 GraphQL API 添加两个自定义变更。以下是它们的 SDL 定义应该是什么样子
要实现这些变更,您需要向 Mutation
类型添加两个字段(通过调用 来自 nexus
的 API)
请务必从 nexus
包中导入 stringArg
和 idArg
以使其工作。
GraphQL Nexus 还会生成您的 GraphQL schema 的 SDL 版本,您可以在 ./generated/schema.graphql
中找到它。我们 GraphQL API 的最终版本如下所示
我们的代码优先 GraphQL 文章的 3 个关键要点
这是我们关于代码优先 GraphQL 服务开发系列文章的最后一部分。
GraphQL Nexus 和 nexus-prisma
插件实现了我们两年多来作为 GraphQL 生态系统积极贡献者所积累的经验。在发现了太多 SDL 优先 方法的问题之后,我们对当前涌现的新代码优先工具感到无比兴奋。
我们坚信 GraphQL Nexus(以及其他代码优先方法,例如 TypeGraphQL)将极大地改变未来 GraphQL schema 的构建方式。
以下是本系列的主要要点
- 代码优先方法让您能够以语言习惯的方式构建 GraphQL 服务,无需额外的工具(“您唯一需要的工具是您的编程语言”),同时保留了 SDL 作为沟通工具的优势。
- GraphQL Nexus 让开发者能够使用灵活且类型安全的 API 构建他们的 schema。开发者通过自动补全和构建时错误检查获得惊人的体验。
nexus-prisma
插件构建在 Prisma 模型之上,通过公开和定制自动生成的 CRUD 构建块,让开发者能够构建 GraphQL API。
今天就来试试 nexus-prisma
吧 🙌
您可以通过几种方式试用 nexus-prisma
。您可以按照文档中的 入门指南 部分,或探索我们的 TypeScript GraphQL 示例。
请通过提交 GitHub Issue 或在我们的 Slack 中分享您的反馈。
非常感谢我们的开源工程师 Flavian Desverne 在 nexus-prisma
插件上的出色工作 💪✨
不要错过下一篇文章!
订阅 Prisma 新闻通讯