GraphQL

内省

我们有时候会需要去问 GraphQL Schema 它支持哪些查询。GraphQL 通过内省系统让我们可以做到这点!

在我们的星战例子里,文件 starWarsIntrospection-test.js 包含了一系列展示了内省系统的查询,它也是一个测试文件,用来检验参考实现的内省系统。

如果是我们亲自设计了类型,那我们自然知道哪些类型是可用的。但如果类型不是我们设计的,我们也可以通过查询 __schema 字段来向 GraphQL 询问哪些类型是可用的。一个查询的根类型总是有 __schema 这个字段。现在来试试,查询一下有哪些可用的类型。

# { "graphiql": true }
{
  __schema {
    types {
      name
    }
  }
}







哇,有好多类型!它们都是什么?我们来总结一下:

  • Query, Character, Human, Episode, Droid - 这些是我们在类型系统中定义的类型。
  • String, Boolean - 这些是内建的标量,由类型系统提供。
  • __Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive - 这些有着两个下划线的类型是内省系统的一部分。

现在,来试试找到一个可以探索出有哪些可用查询的地方。当我们设计类型系统的时候,我们确定了一个所有查询开始的地方,来问问内省系统它是什么!

# { "graphiql": true }
{
  __schema {
    queryType {
      name
    }
  }
}

这和我们在类型系统那章里说的一样,Query 类型是我们开始的地方!注意这里的命名只是一个惯例,我们也可以把 Query 取成别的名字,只要我们把它定义为所有查询出发的地方,它也依然会在这里被返回。尽管如此,还是把它命名为 Query 吧,这是一个有用的惯例。

有时候也需要检验一个特定的类型。来看看 Droid 类型:

# { "graphiql": true }
{
  __type(name: "Droid") {
    name
  }
}

如果我们想要更了解 Droid 呢?例如,它是一个接口还是一个对象?

# { "graphiql": true }
{
  __type(name: "Droid") {
    name
    kind
  }
}

kind 返回一个枚举类型 __TypeKind,其中一个值是 OBJECT。如果我们改问 Character,我们会发现它是一个接口:

# { "graphiql": true }
{
  __type(name: "Character") {
    name
    kind
  }
}

对于一个对象来说,知道它有哪些字段是很有用的,所以来问问内省系统 Droid 有哪些字段:

# { "graphiql": true }
{
  __type(name: "Droid") {
    name
    fields {
      name
      type {
        name
        kind
      }
    }
  }
}




这些正是我们为 Droid 定义的字段!

id 看起来有点儿奇怪,这个类型没有名字。这是因为它是一个 NON_NULL 类型的“包装” 。如果我们请求它的 ofType 字段,我们会发现它是 ID ,告诉我们这是一个非空的 ID。

相似地,friendsappearsIn 都没有名字,因为它们都是 LIST 包装类型。我们可以看看它们的 ofType,就能知道它们是装什么东西的列表。

# { "graphiql": true }
{
  __type(name: "Droid") {
    name
    fields {
      name
      type {
        name
        kind
        ofType {
          name
          kind
        }
      }
    }
  }
}





最后我们来看看内省系统特别适合用来开发工具的特性,我们来向内省系统请求文档!

# { "graphiql": true }
{
  __type(name: "Droid") {
    name
    description
  }
}

因此我们可以通过内省系统接触到类型系统的文档,并做出文档浏览器,或是提供丰富的 IDE 体验。

这些只是内省系统的浅浅一层。我们还可以查询枚举值、某个类型实现了什么接口等等,我们甚至可以对内省系统内省。关于这个主题的详细说明可以看规范的“Introspection”部分,以及 GraphQL.js 中的 introspection 文件,它包含了符合规范的一个内省系统的实现。