我们如何递归地内省 GraphQL 模式?
How can we introspect a GraphQL schema recursively?
如果客户不知道schema,想反省理解一个GraphQLAPI,好像GraphQL可能不支持递归反省。有关我的观点,请参见以下示例
首先,以下是我的高级架构定义:
// schema.js
...
...
const AuthorType = new GraphQLObjectType({
name: "Author",
description: "This represent an author",
fields: () => ({
id: {type: new GraphQLNonNull(GraphQLString)},
name: {type: new GraphQLNonNull(GraphQLString)},
twitterHandle: {type: GraphQLString}
})
});
const PostType = new GraphQLObjectType({
name: "Post",
description: "This represent a Post",
fields: () => ({
id: {type: new GraphQLNonNull(GraphQLString)},
title: {type: new GraphQLNonNull(GraphQLString)},
body: {type: GraphQLString},
author: {
type: AuthorType,
resolve: function(post) {
return _.find(Authors, a => a.id == post.author_id);
}
}
})
});
// This is the Root Query
const BlogQueryRootType = new GraphQLObjectType({
name: 'BlogAppSchema',
description: "Blog Application Schema Query Root",
fields: () => ({
authors: {
type: new GraphQLList(AuthorType),
description: "List of all Authors",
resolve: function() {
return Authors
}
},
posts: {
type: new GraphQLList(PostType),
description: "List of all Posts",
resolve: function() {
return Posts
}
}
})
});
当有人使用以下查询子句查询架构时:
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
}
}
}
}
她得到以下结果:
{
"data": {
"__type": {
"name": "BlogAppSchema",
"fields": [
{
"name": "authors",
"description": "List of all Authors",
"type": {
"name": null
}
},
{
"name": "posts",
"description": "List of all Posts",
"type": {
"name": null
}
}
]
}
}
}
阅读源码,我们知道authors是一个AuthorType的列表。但是,无法访问源代码的用户如何从上面得到的结果中进一步反省 'authors' 字段(这里的类型字段显示 "null" )?她似乎无法从上面的结果中知道 authors
是 Author
的列表。有没有办法让她进一步反省?
name
字段 returns 为空,因为您的 AuthorType
是用 GraphQLList 包装器包装的。这意味着该字段正在返回有关包装器的信息,而不是基础类型。要获取类型,您必须修改您的请求:
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
kind # this will show NON_NULL, LIST, SCALAR or OBJECT
ofType { # if NON_NULL or LIST what is it a non-null or list *of*
name
kind
# other fields, like "fields" which will be populated for an OBJECT
}
}
}
}
}
如果您使用多个包装器(即 [Author]! 或 [Author!]!),您将需要 "go deeper" 并请求嵌套的 ofType
字段:
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
}
}
}
}
如果 kind
是 OBJECT
,它的 fields
字段将被适当填充。然后,您可以请求每个字段的详细信息,如上所示。当然,如果 这些 字段返回了任何 OBJECT,则您必须指定要从这些字段中获取的信息。
您可以阅读更多关于内省的内容here。
内省可能会很混乱。如果您需要一种方式让 GraphQL 端点的使用者探索架构,GraphiQL 是一种更加用户友好的方式。还有动态生成文档的方法 (like this)。
有什么方法可以自动递归查询它,而不是像 Daniel Rearden 提到的那样
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
}
}
}
}
意思是我们不必指定所有这些深层嵌套的 ofType
查询?
如果客户不知道schema,想反省理解一个GraphQLAPI,好像GraphQL可能不支持递归反省。有关我的观点,请参见以下示例
首先,以下是我的高级架构定义:
// schema.js
...
...
const AuthorType = new GraphQLObjectType({
name: "Author",
description: "This represent an author",
fields: () => ({
id: {type: new GraphQLNonNull(GraphQLString)},
name: {type: new GraphQLNonNull(GraphQLString)},
twitterHandle: {type: GraphQLString}
})
});
const PostType = new GraphQLObjectType({
name: "Post",
description: "This represent a Post",
fields: () => ({
id: {type: new GraphQLNonNull(GraphQLString)},
title: {type: new GraphQLNonNull(GraphQLString)},
body: {type: GraphQLString},
author: {
type: AuthorType,
resolve: function(post) {
return _.find(Authors, a => a.id == post.author_id);
}
}
})
});
// This is the Root Query
const BlogQueryRootType = new GraphQLObjectType({
name: 'BlogAppSchema',
description: "Blog Application Schema Query Root",
fields: () => ({
authors: {
type: new GraphQLList(AuthorType),
description: "List of all Authors",
resolve: function() {
return Authors
}
},
posts: {
type: new GraphQLList(PostType),
description: "List of all Posts",
resolve: function() {
return Posts
}
}
})
});
当有人使用以下查询子句查询架构时:
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
}
}
}
}
她得到以下结果:
{
"data": {
"__type": {
"name": "BlogAppSchema",
"fields": [
{
"name": "authors",
"description": "List of all Authors",
"type": {
"name": null
}
},
{
"name": "posts",
"description": "List of all Posts",
"type": {
"name": null
}
}
]
}
}
}
阅读源码,我们知道authors是一个AuthorType的列表。但是,无法访问源代码的用户如何从上面得到的结果中进一步反省 'authors' 字段(这里的类型字段显示 "null" )?她似乎无法从上面的结果中知道 authors
是 Author
的列表。有没有办法让她进一步反省?
name
字段 returns 为空,因为您的 AuthorType
是用 GraphQLList 包装器包装的。这意味着该字段正在返回有关包装器的信息,而不是基础类型。要获取类型,您必须修改您的请求:
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
kind # this will show NON_NULL, LIST, SCALAR or OBJECT
ofType { # if NON_NULL or LIST what is it a non-null or list *of*
name
kind
# other fields, like "fields" which will be populated for an OBJECT
}
}
}
}
}
如果您使用多个包装器(即 [Author]! 或 [Author!]!),您将需要 "go deeper" 并请求嵌套的 ofType
字段:
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
}
}
}
}
如果 kind
是 OBJECT
,它的 fields
字段将被适当填充。然后,您可以请求每个字段的详细信息,如上所示。当然,如果 这些 字段返回了任何 OBJECT,则您必须指定要从这些字段中获取的信息。
您可以阅读更多关于内省的内容here。
内省可能会很混乱。如果您需要一种方式让 GraphQL 端点的使用者探索架构,GraphiQL 是一种更加用户友好的方式。还有动态生成文档的方法 (like this)。
有什么方法可以自动递归查询它,而不是像 Daniel Rearden 提到的那样
{
__type(name: "BlogAppSchema") {
name
fields {
name
description
type {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
}
}
}
}
意思是我们不必指定所有这些深层嵌套的 ofType
查询?