GraphQL(一)基础介绍及应用示例

简介: 本文为GraphQL的基础介绍及应用示例,主要介绍GraphQL的应用场景、优缺点及基础语法与使用。GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

应用场景及优缺点

引自译文GraphQL:它的优点、缺点和备选方案,原文为Why GraphQL: Advantages and Disadvantages

应用场景

GraphQL是由Facebook在 2012 年创立的一门开源查询语言。在它开源之前,Facebook就已经在内部移动端应用中使用过。GraphQL作为通用的REST架构的替代方案而被开发出来,它允许客户端只请求其需要的数据——不多也不少,一切在客户端的主导下。

在一个RESTful架构下,因为后端开发人员定义在各个 URL 的资源上返回的数据,而不是前端开发人员来提出数据需求,使得按需获取数据会非常困难。经常前端需要请求一个资源中所有的信息,即便只需要其中的一部分数据。这个问题被称之为过度获取(overfetching)。最恶劣的场景下,一个客户端应用不得不请求多个而不是一个资源,这通常会发起多个网络请求。这不仅会造成过度获取的问题,也会造成瀑布式的网络请求(waterfall network requests)。那么将像 GraphQL 之类的查询语言,不仅在服务端程使用,也应用到客户端的话,客户端来决定需要什么数据,这样只需要发送一个请求到服务端。在 Facebook 的 GraphQL 移动端开发场景下,这极大地减少了忘了请求,因为 GraphQL 一次只需要发起一个请求,并且传输中数据数量也减少了。

优点

声明式地数据获取

GraphQL在使用查询语句式,使用声明式的方式获取数据。客户端在一个查询请求中,选择需要的数据和相关的字段实体。客户端根据其 UI 来决定需要的字段。你可以说这是 UI 驱动地数据获取。毕竟,GraphQL 提供了极佳的关注点分离方式:客户端知道它需要什么数据,服务端知道数据的结构,以及如何从一些数据源(比如数据库、微服务、第三方 API)中拉取数据。

比方说,Airbnb 使用 GraphQL的例子,在 Airbnb 中的一个搜索界面,经常需要搜索房屋的住房体验和其他相关的一些信息,为了能在一个请求中检索所有的数据,一个 GraphQL 查询会根据 UI 选择数据中的一部分达到完美的匹配。

单一数据源(Single Source of Truth)

在 GraphQL 应用中存在者单一数据源:GraphQL schema。它提供了一个所有可用数据检索的源头。鉴于 GraphQL 的 schema 通常会在服务端定义,客户端可以基于 schema 读取(query)和写入(mutation)数据。因此,服务端提供了所有可用的信息,客户端只需要执行 GraphQL 查询获取部分数据,或者通过 GraphQL 修改变更部分数据。

拼接 GraphQL Schema

拼接 Schema 使得多个 schema可以聚合成一个。什么时候你需要考虑这个?考虑一下后端的微服务架构。每个微服务处理特定域的业务逻辑和数据。因此,每个微服务都可以定义自己的GraphQL架构。之后,使用 Schema 拼接将所有 Schema 聚合到一个可以被客户端访问的 Schema 中。最终,每个微服务都可以拥有自己的 GraphQL 端点,而一个 GraphQL API网关将所有 schema 合并到一个全局 schema 中,以便使得客户端可以使用。

GraphQL 自省(Introspection)

GraphQL 自省允许通过 GraphQL API 检索 GraphQL schema。因为 schema 包含了包含了 GraphQL API 可以获得的所有数据信息,本身就是一份完美的自动生成的 API 文档。不仅仅是 API 的文档,也允许客户端通过mock GraphQL 的 schema 达到测试的目的,或者使用 schema 拼接的接口检索多个微服务的 schema。

缺点

N+1问题,解决方案:DataLoader

GraphQL 查询的复杂性

当一个客户端需要一次查询很多嵌套字段时,前端开发通常不能很清楚他正在通过服务端访问不同的数据库获取过多的数据。这需要一种机制(比如最深查询深度、查询复杂度权重、避免递归、持久化查询)来制止来自客户端的(性能)昂贵的查询。

查询频率限制

另一个问题是频率限制,在 REST 中,可以简单的声明”一天之中,我们只允许请求这么多资源“,在一个独立的 GraphQL 操作中很难做到这一点,因为任何操作的开销都可以是廉价的或者昂贵的。这就是那些有着公共 GraphQL API 的公司提出的特定速率限制计算,通常可以归结为前面提到的最大查询深度和查询复杂度权重问题。

GraphQL 缓存

一个简单缓存,相比 REST,在 GraphQL 中实现会变得极其复杂。在 REST 中你通过 URL 访问资源,因此你可以在资源级别实现缓存,因为资源使用 URL 作为其标识符。在 GraphQL 中就复杂了,因为即便它操作的是同一个实体,每个查询都各不相同。比如,一个查询中,你可能只会请求一个作者的名字,但是在另外一次查询中你可能也想知道他的电子邮箱地址。这就需要你有一个更加健全的机制中来确保字段级别的缓存,实现起来并不简单。不过,多数基于 GraphQL 构建的类库都提供了开箱即用的缓存机制。

对象类型和字段

GraphQL默认标量类型

  • Int:有符号 32 位整数。
  • Float:有符号双精度浮点值。
  • String:UTF‐8 字符序列。
  • Boolean:true 或者 false。
  • ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
type Starship {
   
  id: ID!
  nick: [String!]!
  length(unit: LengthUnit = METER): Float
}
  • Starship为GraphQL 对象类型
  • id/nick/lengthStarship类型上的字段
  • nick为非空数组,其数组元素为String且非空

对象类型和字段详细定义见 https://graphql.cn/learn/schema/#type-language

查询和变更类型

schema内有两个特殊类型,定义了每一个GraphQL查询的入口

每一个 GraphQL 服务都有一个query类型,可能有一个mutation类型

schema {
   
  "查询"
  query: Query
  "变更"
  mutation: Mutation
}

示例:

# 定义查询接口
type Query {
   
    # 无参, 返回字符串
    hello: String
    # 字段参数且不能为空, 返回普通对象
    bookById(id: ID!): Book
    # 对象参数, 返回列表
    books(book: BookInput): [Book]
}

# 定义修改接口
type Mutation {
   
    hello: String
}

应用示例

一个 GraphQL 查询在被验证后,GraphQL 服务器会将之执行,并返回与请求的结构相对应的结果,该结果通常会是 JSON 的格式。

schema

type Query {
   
  human(id: ID!): Human
}

type Human {
   
  name: String
  appearsIn: [Episode]
  starships: [Starship]
}

enum Episode {
   
  NEWHOPE
  EMPIRE
  JEDI
}

type Starship {
   
  name: String
}

请求参数

{
   
  human(id: 1002) {
   
    name
    appearsIn
    starships {
   
      name
    }
  }
}

响应结果

{
   
  "data": {
   
    "human": {
   
      "name": "Han Solo",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "starships": [
        {
   
          "name": "Millenium Falcon"
        },
        {
   
          "name": "Imperial shuttle"
        }
      ]
    }
  }
}

参考资料:

  1. graphql
  2. graphql-java-tools
  3. [译]为什么选用 GraphQL:它的优点、缺点和备选方案
相关文章
|
9天前
|
安全 前端开发 API
ThinkPHP5 API模块开发规范与示例
【7月更文挑战第6天】本技术文档旨在指导开发者如何完全遵循ThinkPHP5框架的开发规范来构建RESTful API模块。ThinkPHP5(简称TP5)是一款基于PHP的轻量级MVC框架,其简洁、高效的特点非常适合快速开发Web应用及API接口。以下是创建API模块的基本步骤、最佳实践以及代码示例。
24 0
|
15天前
|
JavaScript API 开发者
GraphQL API开发入门:比RESTful更高效的数据查询方式
**GraphQL API开发入门摘要** GraphQL是一种更高效的数据查询方式,解决RESTful API的过度或不足获取数据问题。它允许客户端按需获取数据,减少网络传输,支持一次请求获取多资源。强类型和自描述特性方便了开发。文章通过一个简单的Node.js示例,展示如何使用`apollo-server-express`搭建GraphQL服务器,包括定义Schema、实现Resolver和创建服务器。通过测试,显示了GraphQL如何提供精确数据和优化查询效率。对于复杂数据需求,GraphQL是现代API设计的有效选择。
23 0
|
25天前
|
JSON 中间件 API
中间件API示例(以Express.js为例)
【6月更文挑战第14天】
23 8
|
2月前
|
Linux API 网络架构
Rest API请求管理最佳实践:RestClient-cpp库的应用案例
Rest API请求管理最佳实践:RestClient-cpp库的应用案例
|
2月前
|
数据可视化 测试技术 API
Swagger--API表达工具
Swagger--API表达工具
54 2
|
2月前
|
API 网络架构
解释 RESTful API,以及如何使用它构建 web 应用程序。
解释 RESTful API,以及如何使用它构建 web 应用程序。
104 0
|
2月前
|
前端开发 API 开发者
GraphQL:重新定义数据交互的未来
在当今信息爆炸的时代,数据的交互变得越来越复杂。传统的RESTful API在满足前端应用需求方面存在一些限制和不便之处。而GraphQL作为一种创新的数据查询语言,通过其灵活性和高效性,为开发者提供了更好的数据交互解决方案。本文将深入介绍GraphQL的概念与实践,探讨其如何重新定义数据交互的未来。
|
JSON 前端开发 API
如何使用GraphQL进行前端数据交互
如何使用GraphQL进行前端数据交互
|
8月前
|
XML JSON API
API类型和集成规范指南
API类型和集成规范指南
130 0
|
前端开发 JavaScript API
浅谈前端编程语言及API数据返回展示
前端编程语言是指用于开发网站和应用程序的编程语言。