GraphQL 是一种用于查询和操作 API 的查询语言,由 Facebook 开发。相较于 REST API,GraphQL 具有更高的灵活性和更少的数据传输量。
GraphQL 的核心概念之一是 type,用于定义数据的结构和关系。在 GraphQL 中,所有数据类型都必须定义为 type,包括查询和变量。本文将探讨 GraphQL 的 type 和 schema 设计及相关建议。
Type 的设计
如前所述,GraphQL 中所有的数据类型都必须定义为 type,这包括 scalar 类型和 object 类型。我们来看一个例子:
-- -------------------- ---- ------- ----- ----------- - ------ ---- ----------- ------ - ---- ------ - --- --- ------ ---- ----------- ------ ---------- --------- -------- -------- -
上面的例子中定义了两个类型:ReviewInput
和 Review
。ReviewInput
定义了一个输入类型,用于创建或更新 Review
对象,它包含了 stars
和 commentary
两个属性。
Review
是一个对象类型,它具有 id
、stars
、commentary
、createdAt
和 product
五个属性。其中 stars
、commentary
和 createdAt
都是标量类型,而 product
是一个对象类型。
在定义 type 时,有几个需要注意的点:
1. 尽量使用标量类型而不是自定义类型
GraphQL 支持的标量类型包括:Int、Float、String、Boolean 和 ID。标量类型是基本数据类型,通常不需要进一步定义。自定义类型应该是对象类型,像上面的 Review
一样。
在使用自定义类型时,必须要保证它真的必要。避免过深的嵌套,导致查询复杂度增加,接口响应变慢。
2. 定义字段时使用描述性名称
更好的字段名称可以提高查询的可读性,降低沟通成本。
3. 考虑数据的拆分和意义的分离
GraphQL 中的 type 不应该只是展示 API 返回的数据,还要关注数据存在的结构及其关系。可能会有多个类型包含相似的数据,在这种情况下,将其拆分为一个共同的类型或使用接口进行类型继承非常有帮助。
4. 定义好类型的默认值
在定义 type 时,最好指定默认值,这样可以保证 type 不会返回空值,也可以避免查询操作出现错误。
Schema 的设计
GraphQL schema 就是 type 的组合,Schema 对外暴露了 API 所支持的查询、变更、订阅等操作。GraphQL schema 通常由 type 和 resolver 组成。
一个简单示例:
type Query { me: User } type User { id: ID! name: String! }
这个示例定义了两个类型:Query
和 User
。Query
是一个根类型,表示 API 的入口点。User
定义了一个用户对象,具有 id
和 name
两个属性。
在定义 schema 时,有几个需要注意的点:
1. 将 schema 的类型和操作分开
GraphQL schema 中一般会定义 Query、Mutation 以及 Subscription 等操作。在定义 schema 时,建议将它们拆开,这样可以提高代码可读性和可维护性。
2. 继承和接口的使用
GraphQL schema 中可以使用接口和继承。在 schema 的设计中,通常建议使用接口来设计 type,这样可以允许多个 type 实现该接口。
3. 设计良好的查询以降低响应负载
合理的 schema 设计可以降低响应负载。例如,最好将查询细分为一些小查询而不是一个大查询,这样可以更有效地应对大量数据的查询。
建立一个简单的 GraphQL API
本节将用示例代码演示建立一个简单的 GraphQL API。假设我们要创建一个 API,用于查询和添加电影评论。
1. 安装相关依赖和配置基本结构
我们首先需要安装相关的依赖:
npm install graphql express express-graphql
然后,创建一个基本的 Express 应用程序:
-- -------------------- ---- ------- ----- ------- - ------------------- ----- ----------- - --------------------------- ----- ------ - -------------------- ----- --- - ---------- -------- ----------- ------------- ------- --------- ----- --- -- ---------------- -- -- - ------------------- ------- -- ---- ------- ---
这里使用了 graphqlHTTP
中间件来处理所有的 GraphQL 请求。我们定义了一个 /graphql
的路由,并将 schema
传递给中间件。
2. 定义电影对象类型
我们首先要定义电影对象的类型。在这个例子中,电影对象应该包含标题和描述。
-- -------------------- ---- ------- ----- - ------------------ -------------- -------------- - - ------------------- ----- --------- - --- ------------------- ----- -------- ------- -- -- -- ------ - ----- -------------- -- ------------ - ----- -------------- -- --- ---
在这个代码中,我们使用 GraphQLObjectType
来定义电影类型。它拥有一个名叫 name
的属性用于定义类型名称,以及 fields
属性,它是一个函数,返回的是一个包含所有字段的对象。
在这种情况下,我们定义了两个属性:title
和 description
。它们都是字符串类型。
3. 定义根查询对象 Type
我们需要定义一个根查询对象 type 来支持 API 查询操作。在这个例子中,我们只需要返回一个电影。
-- -------------------- ---- ------- ----- ------------- - --- ------------------- ----- -------- ------- -- -- -- ------ - ----- ---------- -------- -- -- -- ------ ----- ------ ------------ -- ----- ------- --- -- --- ---
在这个代码中,我们定义了一个名叫 movie
的字段,它会返回一个电影对象。
在 resolve
函数中,我们可以定义如何解析它。这个 API 没有访问数据库,所以我们硬编码了一个电影。
4. 设计好 schema
现在,我们需要将根查询对象 type 和电影对象 type 组合到一个 schema 中:
const schema = new GraphQLSchema({ query: rootQueryType, });
现在创建完成了,我们访问 http://localhost:4000/graphql
就可以看到图形化的 GraphQL debugger 页面,请求 GraphQL API 了,如下所示:
输入如下代码来查询电影:
{ movie { title description } }
会得到如下返回:
{ "data": { "movie": { "title": "Star Wars", "description": "A space opera" } } }
如你所见,GraphQL API 返回了我们期望的电影对象。
总结
本文仅仅介绍了如何在 GraphQL 中定义 type 和 schema。最佳实践通常是由项目决定的 ,在设计 GraphQL type 和 schema 的过程中,尽量保持简单、具有可扩展性、易于维护。另外,最好在项目开始之前花时间设计 schem 以及一个好的数据结构,这可以节省追溯错误以及 API 重构的时间。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651d027995b1f8cacd486413