Logo
Section 1 / 2

模式内省简介

了解 GraphQL 模式内省。

导入

模式内省简介

了解 GraphQL 模式内省。

检查一个 GraphQL 服务器支持哪些查询或操作非常重要。为了实现这一功能,GraphQL 提供了内省(introspection)系统。

当我们自己设计类型系统时,我们知道有哪些类型可用。但如果我们没有参与设计,就可以通过查询 __schema 来向 GraphQL 询问。该字段始终在查询的根类型上开放。我们来问问 GraphQL 有哪些类型可用:

1{ 2 __schema { 3 types { 4 name 5 } 6 } 7}

使用上述查询,我们将得到如下响应:

1{ 2 "data": { 3 "__schema": { 4 "types": [ 5 { 6 "name": "PizzaStatus" 7 }, 8 { 9 "name": "Pizza" 10 }, 11 { 12 "name": "Int" 13 }, 14 { 15 "name": "String" 16 }, 17 { 18 "name": "Topping" 19 }, 20 { 21 "name": "ToppingInput" 22 }, 23 { 24 "name": "Query" 25 }, 26 { 27 "name": "Mutation" 28 }, 29 { 30 "name": "Boolean" 31 }, 32 { 33 "name": "__Schema" 34 }, 35 { 36 "name": "__Type" 37 }, 38 { 39 "name": "__TypeKind" 40 }, 41 { 42 "name": "__Field" 43 }, 44 { 45 "name": "__InputValue" 46 }, 47 { 48 "name": "__EnumValue" 49 }, 50 { 51 "name": "__Directive" 52 }, 53 { 54 "name": "__DirectiveLocation" 55 } 56 ] 57 } 58 } 59}

哇,这么多类型!它们分别是什么?我们可以将它们分为以下几类:

  • Query、Mutation、Pizza、PizzaStatus、Topping 和 ToppingInput:这些是我们自己在类型系统中定义的类型。

  • Int、String 和 Boolean:这些是类型系统提供的内置标量类型。

  • __Schema、__Type、__TypeKind、__Field、__InputValue、__EnumValue、__Directive 和 __DirectiveLocation:这些是以双下划线开头的保留类型,属于内省系统的一部分。

查询类型的内省

在设计类型系统时,我们指定了所有查询的起始类型。现在我们可以通过内省系统来查询当前可用的查询操作有哪些:

1{ 2 __schema { 3 queryType { 4 name 5 fields { 6 name 7 args { 8 name 9 type { 10 kind 11 name 12 } 13 } 14 type { 15 kind 16 name 17 } 18 } 19 } 20 } 21}

将上述查询发送给 GraphQL 服务器后,我们会收到与类型系统课程中所学内容一致的 JSON 响应:

1{ 2 "data": { 3 "__schema": { 4 "queryType": { 5 "name": "Query", 6 "fields": [ 7 { 8 "name": "pizzas", 9 "args": [ 10 { 11 "name": "pizza", 12 "type": { 13 "kind": "SCALAR", 14 "name": "String" 15 } 16 } 17 ], 18 "type": { 19 "kind": "LIST", 20 "name": null 21 } 22 }, 23 { 24 "name": "pizza", 25 "args": [ 26 { 27 "name": "id", 28 "type": { 29 "kind": "SCALAR", 30 "name": "Int" 31 } 32 } 33 ], 34 "type": { 35 "kind": "NON_NULL", 36 "name": null 37 } 38 } 39 ] 40 } 41 } 42 } 43}

我们来解析一下这个响应:

  • queryType 和 name:描述了 GraphQL 的根操作类型,通常是 Query 或 Mutation。
  • fields 中的 name 字段列出了 GraphQL 服务器上所有可用的查询操作,在本例中为 pizza 和 pizzas。
  • 要调用某个操作,我们需要知道需要传递哪些参数。这些参数在响应中以 args 形式呈现,并说明了应传入的参数类型。例如,pizza 操作需要一个名为 id 的 Int 类型参数。

变更类型的内省

Mutation 类型与 Query 类型非常相似。因此,只需将 queryType 替换为 mutationType,即可获取所有可用的变更操作:

1{ 2 __schema { 3 mutationType { 4 name 5 fields { 6 name 7 args { 8 name 9 type { 10 kind 11 name 12 } 13 } 14 type { 15 kind 16 name 17 } 18 } 19 } 20 } 21}

将上述查询发送至 GraphQL 服务器后,会收到如下响应:

1{ 2 "data": { 3 "__schema": { 4 "mutationType": { 5 "name": "Mutation", 6 "fields": [ 7 { 8 "name": "createPizza", 9 "args": [ 10 { 11 "name": "pizza", 12 "type": { 13 "kind": "SCALAR", 14 "name": "String" 15 } 16 }, 17 { 18 "name": "toppings", 19 "type": { 20 "kind": "NON_NULL", 21 "name": null 22 } 23 } 24 ], 25 "type": { 26 "kind": "NON_NULL", 27 "name": null 28 } 29 }, 30 { 31 "name": "updatePizza", 32 "args": [ 33 { 34 "name": "id", 35 "type": { 36 "kind": "NON_NULL", 37 "name": null 38 } 39 }, 40 { 41 "name": "pizza", 42 "type": { 43 "kind": "SCALAR", 44 "name": "String" 45 } 46 }, 47 { 48 "name": "toppings", 49 "type": { 50 "kind": "LIST", 51 "name": null 52 } 53 } 54 ], 55 "type": { 56 "kind": "NON_NULL", 57 "name": null 58 } 59 } 60 ] 61 } 62 } 63 } 64}

我们来分析一下响应内容:

  • 当前根操作是 Mutation,由 mutationType 和其 name 字段表示。
  • fields 中的 name 列出了服务器上所有可用的变更操作,即 createPizza 和 updatePizza。
  • 要调用某个变更操作,需了解所需参数。这些参数在响应中以 args 形式提供,并标明了参数类型。例如,createPizza 需要一个 pizza 参数(字符串类型),以及一个 toppings 参数(不可为空)。

特定类型的内省

我们也可以查询特定类型的信息。例如,查看 Pizza 类型的结构:

1{ 2 __type(name: "Pizza") { 3 name 4 fields { 5 name 6 type { 7 name 8 kind 9 ofType { 10 name 11 kind 12 } 13 } 14 } 15 } 16}

我们来分解这个 GraphQL 查询:

  • 使用 __type 并传入参数 name: "Pizza",表示我们想获取关于 Pizza 类型的信息。
  • fields 中的 name 字段类似于 queryType 或 mutationType 的字段,但此处返回的是 Pizza 类型自身包含的所有字段,即 id、pizza、toppings 和 status。
  • 在请求中加入 ofType 可以获取字段更详细的类型信息。例如,status 是必填字段,其类型为名为 PizzaStatus 的枚举(Enum)。

响应如下:

1{ 2 "data": { 3 "__type": { 4 "name": "Pizza", 5 "fields": [ 6 { 7 "name": "id", 8 "type": { 9 "name": null, 10 "kind": "NON_NULL", 11 "ofType": { 12 "name": "Int", 13 "kind": "SCALAR" 14 } 15 } 16 }, 17 { 18 "name": "pizza", 19 "type": { 20 "name": null, 21 "kind": "NON_NULL", 22 "ofType": { 23 "name": "String", 24 "kind": "SCALAR" 25 } 26 } 27 }, 28 { 29 "name": "toppings", 30 "type": { 31 "name": null, 32 "kind": "NON_NULL", 33 "ofType": { 34 "name": null, 35 "kind": "LIST" 36 } 37 } 38 }, 39 { 40 "name": "status", 41 "type": { 42 "name": null, 43 "kind": "NON_NULL", 44 "ofType": { 45 "name": "PizzaStatus", 46 "kind": "ENUM" 47 } 48 } 49 } 50 ] 51 } 52 } 53}

利用这一特性,我们可以通过内省访问类型系统的文档信息,进而构建文档浏览器或功能丰富的 IDE 体验。

测试 GraphQL 模式内省

在 GraphQL Playground 中测试模式内省功能。

模式执行

模式内省测验