2019年2月12日

将 GraphQL Nexus 与数据库结合使用

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

Using GraphQL Nexus with a Database

⚠️ 本文已过时,因为它与现已弃用Prisma 1 相关。要了解最新版本的 Prisma,请阅读文档。⚠️

回顾:使用 GraphQL Nexus 进行代码优先开发

在上一篇文章中,我们介绍了 GraphQL Nexus,一个为 TypeScript 和 JavaScript 启用代码优先开发的 GraphQL 库。使用 Nexus,GraphQL 模式是编程定义和实现的。因此,它遵循其他语言中 GraphQL 服务器的成熟方法,例如 sangria-graphql (Scala)、graphlq-rubygraphene (Python)。

今天的文章是关于将您基于 Nexus 的 GraphQL 服务器连接到数据库,使用 Prisma 客户端以及新的 nexus-prisma 插件。我们稍后将通过一个从零开始构建博客应用 GraphQL API 的实际示例来指导您。

nexus-prisma 支持 PostgreSQL、MySQL 和 MongoDB。有关文档,请点击此处


TLDR:nexus-prisma 插件的优势

  • 为您的 Prisma 模型在 GraphQL 中执行 CRUD 操作
  • 自定义您的 Prisma 模型,例如隐藏某些字段添加计算字段
  • 完全类型安全:为 GraphQL 模式和数据库提供一致的类型集
  • 与 GraphQL 生态系统兼容(例如 apollo-servergraphql-yoga 等)

理解 nexus-prisma 工作流

Prisma 客户端作为 ORM 替代品

如果您以前没有使用过 Prisma,这里简要介绍一下它的工作原理

  1. 定义您的数据模型或让 Prisma 内省您现有的数据库
  2. 生成您的 Prisma 客户端,即一个类型安全的数据库客户端
  3. 在应用程序(例如 GraphQL API)中使用 Prisma 客户端访问您的数据库

nexus-prisma 插件的幕后

当将 nexus-prisma 添加到组合中时,还有另一个步骤:调用 nexus-prisma-generate codegen CLI。它为您的 Prisma 模型生成一个成熟的 GraphQL CRUD API 的构建块,例如对于 User 模型,它包括

  • 查询
    • user(...): User!:获取单个记录
    • users(...): [User!]!:获取记录列表
    • usersConnection(...): UserConnection!Relay 连接和聚合
  • 突变
    • createUser(...): User!:创建新记录
    • updateUser(...): User:更新记录
    • deleteUser(...): User:删除记录
    • updatesManyUsers(...): BatchPayload!:批量更新多条记录
    • deleteManyUsers(...): BatchPayload!:批量删除多条记录
  • GraphQL 输入类型
    • UserCreateInput:包装记录的所有字段
    • UserUpdateInput:包装记录的所有字段
    • UserWhereInput:为记录的所有字段提供过滤器
    • UserWhereUniqueInput:为记录的唯一字段提供过滤器
    • UserUpdateManyMutationInput:包装可以批量更新的字段
    • UserOrderByInput:按字段指定升序或降序

UserCreateInputUserUpdateInput 在处理关系字段的方式上有所不同。

在使用 nexusnexus-prisma 编写 GraphQL 服务器代码时,您可以通过公开和自定义这些操作来满足您自己的 API 需求

Writing GraphQL server code with nexus and nexus-prisma

生成 CRUD 构建块后,您可以使用 nexus-prisma 中的 prismaObjectType 开始公开(和自定义)它们。以下代码片段描述了一个基于 Prisma 和 nexus-prisma 为待办事项列表应用程序提供 GraphQL API 的实现

我们将 prismaObjectType 应用于 QueryMutation。对于 Query,我们保留所有字段(即 todotodoestodoesConnection)。对于 Mutation,我们使用 prismaFields 来自定义公开的操作。

prismaFields 允许我们选择要公开的操作。在这种情况下,我们只想保留创建模型的操作(createTodo)。从生成的 CRUD 构建块中,我们既不包括 updateTodo 也不包括 deleteTodo,而是实现我们自己的 markAsDone(id: ID!) 突变来勾选某个 Todo


示例:从标准 CRUD 到自定义 GraphQL API

现在,让我们快速了解一个标准的 Prisma 用例,看看如何通过几个简单的步骤快速为博客应用程序构建 GraphQL API。我们将做以下工作

  1. 使用 TypeScript 设置 Prisma 项目(使用免费演示数据库)
  2. 定义模型、迁移数据库并生成 Prisma 客户端
  3. 通过 nexus-prisma 公开完整的 CRUD GraphQL API
  4. 通过 nexus-prisma 自定义 GraphQL API

如果您想跟着做,您需要安装 Prisma CLI

1) 使用 TypeScript、nexusnexus-prisma 设置 Prisma 项目

本节主要涉及您的项目设置。如果您不想编码,请随意跳过此部分,否则请展开以下部分。

使用 Prisma CLI 创建一个简单的 Prisma 项目

在交互式提示中,选择以下选项

  1. 选择 演示服务器(包括 Prisma Cloud 中免费托管的演示数据库)
  2. 在浏览器中通过 Prisma Cloud 认证(如果需要)
  3. 回到终端,确认所有建议值

除了演示服务器,您还可以使用 Docker 在本地运行 Prisma

接下来,您需要配置您的 nexus-prisma 工作流。添加以下依赖项(在 myblog 目录中)

接下来,将以下两行添加到 prisma.yml 的末尾

这确保了只要您对模型进行更改,Prisma 客户端以及生成的 nexus-prisma CRUD 构建块都会更新。

由于我们正在使用 TypeScript,让我们快速添加一个 tsconfig.json

最后,继续添加一个 start 脚本,您将用于开发。它启动一个开发服务器,在后台监视您的文件,并在您编码时更新生成的 SDL 和 Nexus 类型。将其添加到您的 package.json

2) 定义模型、迁移数据库并生成 Prisma 客户端

prisma init 命令在 datamodel.prisma 中创建了一个默认的 User 模型。由于我们正在构建一个博客应用程序,让我们将模型调整为我们的应用程序域

接下来,您需要通过将数据模型应用到数据库来迁移数据库。使用以下命令,datamodel.prisma 中定义的每个模型都将映射到底层数据库中的一个表

因为您之前在 prisma.yml 中配置了 post-deploy 钩子,所以您的 Prisma 客户端和 CRUD 构建块会自动更新。

3) 通过 nexus-prisma 公开完整的 CRUD GraphQL API

在项目的早期阶段,API 公开完整的 CRUD 功能通常很有帮助——随着时间的推移,更严格的 API 要求通常会出现。nexus-prisma 通过提供从完整 CRUD 到定制 API 操作的直接路径,完美地考虑了这一点。

让我们从一个公开定义模型的完整 CRUD 的 GraphQL API 开始(请注意,这包括过滤器、分页和排序)。创建一个名为 index.ts 的新文件,并向其中添加以下代码

在这个简短的教程中,我们不太关注文件结构。有关正确的设置和模块化模式,请查看我们的 graphql-auth 示例。

运行 npm run start 后,您可以在 https://:4000 上打开您的 GraphQL 服务器的 GraphQL Playground。使用您上面编写的少量代码,您已经拥有了一个成熟的 GraphQL CRUD API。

示例查询

示例突变

这是如何工作的?nexus-prisma-generate 生成了一个 GraphQL 模式,该模式为 Prisma 模型(您的 CRUD 构建块)提供了一个 CRUD API。此 GraphQL 模式遵循 OpenCRUD 规范。使用 prismaObjectType 函数,您现在可以公开和自定义该模式的操作。

prismaObjectTypeprismaFields 使用白名单方法,这意味着您需要明确列出要公开的字段。通配符运算符 * 包括所有字段。

Expose full CRUD GraphQL API via nexus-prisma

4) 通过 nexus-prisma 自定义 GraphQL API

在本节中,我们将学习如何自定义 nexus-prisma 的 CRUD GraphQL API。具体来说,我们将

  1. User 模型中隐藏一个字段
  2. Post 模型添加一个计算字段
  3. 隐藏 createPostupdatePost 突变
  4. 添加两个自定义的 createDraftpublish 突变

4.1) 从 User 模型中隐藏一个字段

在本节中,我们将从 User 模型中隐藏 email 字段。

要自定义模型,我们需要将 prismaObjectType 函数应用于它,并将 definition(t) 函数作为选项传递

通过在模型 t 上调用 prismaFields,我们可以自定义公开的字段(及其参数)。因为 email 不包含在列表中,所以它将从我们的 GraphQL API 中删除。

Hide a field from the User model

要应用更改,您需要显式地将 User 传递给 makePrismaSchema 内部的 types 数组

请注意,您的编辑器能够根据生成的 CRUD 构建块建议要传递给 prismaObjectTypeprismaFields 的内容。这意味着当您键入 prismaObjectType('') 并按下 ctrl+space 时,它会建议所有生成的 CRUD 构建块的名称。当调用 t.prismaFields(['']) 时,它会建议 t 的字段

4.2) 为 Post 模型添加一个计算字段

使用 nexus-prisma 的新代码优先方法也使得为 Prisma 模型添加计算字段变得容易。假设您想为 Post 添加一个字段,该字段始终返回完全大写的 title。下面是如何实现它

我们使用来自 graphql-nexust.string(...) API 为我们的模型添加一个新字段。因为它是计算字段(因此不能由 nexus-prisma 自动解析),我们还需要为其附加一个解析器。

Customize the GraphQL API via nexus-prisma

如前所述,您需要将自定义的 Post 模型显式添加到 types 数组中

4.3) 隐藏 createPostupdatePost 突变

与我们从 User 模型中隐藏 email 字段的方式相同,我们也可以从作为生成的 nexus-prisma CRUD 构建块一部分的 Query/Mutation 类型中隐藏操作。

要隐藏 createPostupdatePost,我们再次需要将 definition(t) 作为选项传递给 prismaObjectType。请注意,一旦我们在类型上调用 prismaFields,我们需要显式列出所有要保留的字段(空数组将被解释为“不保留任何操作”)

生成的 CRUD GraphQL API 还包括批量和 upsert 操作,为了简洁起见,我们在此也将其排除。

4. 添加两个自定义的 createDraftpublish 突变

最后,我们向 GraphQL API 添加了两个自定义突变。它们应该看起来像这样的 SDL 定义

要实现这些突变,您需要向 Mutation 类型添加两个字段(通过调用来自 nexus API 的 t.field( ... )

请务必从 nexus 包中导入 stringArgidArg,以使其正常工作。

GraphQL Nexus 还生成 GraphQL 模式的 SDL 版本,您可以在 ./generated/schema.graphql 中找到它。我们的 GraphQL API 的最终版本如下所示


我们代码优先 GraphQL 文章的 3 个主要收获

这是我们关于代码优先 GraphQL 服务器开发系列文章的最后一部分。

GraphQL Nexusnexus-prisma 插件实现了我们作为 GraphQL 生态系统的积极贡献者两年多来所收集到的经验教训。在发现 SDL 优先方法存在太多问题之后,我们对目前正在涌现的新代码优先工具感到非常兴奋。

我们坚信 GraphQL Nexus(以及其他代码优先方法,如 TypeGraphQL)将极大地改变未来 GraphQL 模式的构建方式。

以下是本系列的主要收获

  1. 代码优先方法允许您以语言惯用的方式构建 GraphQL 服务器,而无需额外的工具(“您唯一需要的工具是您的编程语言”),同时保留 SDL 作为通信工具的优势。
  2. GraphQL Nexus 允许开发人员使用灵活且类型安全的 API 构建其模式。由于自动完成和构建时错误检查,开发人员获得了出色的体验。
  3. nexus-prisma 插件基于 Prisma 模型构建,并允许开发人员通过公开和自定义自动生成的 CRUD 构建块来构建 GraphQL API。

立即试用 nexus-prisma 🙌

您可以通过多种方式试用 nexus-prisma。您可以遵循文档中的入门部分,或者探索我们的TypeScript GraphQL 示例

请通过提出 GitHub issue 或在我们的Slack 中联系我们来分享您的反馈。


衷心感谢我们的开源工程师 Flavian Desvernenexus-prisma 插件方面所做的出色工作 💪✨

不要错过下一篇文章!

订阅 Prisma 新闻通讯

© . This site is unofficial and not affiliated with Prisma Data, Inc.