对 GraphQL 中嵌套类型的深度查询返回 NULL
Posted
技术标签:
【中文标题】对 GraphQL 中嵌套类型的深度查询返回 NULL【英文标题】:Deep query to nested types in GraphQL return NULL 【发布时间】:2019-07-05 04:06:02 【问题描述】:有一个奇怪的问题...
对嵌套类型的查询返回 null。
但是,如果我返回父类型中的任何内容 - 解析返回正确的结果
我的代码:
import GraphQLList, GraphQLString, GraphQLID, GraphQLObjectType, GraphQLSchema from 'graphql';
import AdminModel from '../models/Admin.model';
const AdminType = new GraphQLObjectType(
name: 'AdminType',
fields:
_id: type: GraphQLID ,
login: type: GraphQLString ,
password: type: GraphQLString
);
const AdminRooteType = new GraphQLObjectType(
name: 'AdminRooteType',
fields:
getAdmins:
type: new GraphQLList(AdminType),
resolve()
return AdminModel.find()
)
export default new GraphQLSchema(
query: new GraphQLObjectType(
name: 'RootQuery',
fields:
admin:
type: AdminRooteType,
resolve()
// EMPTY RESOLVE - EMPTY RESULT
)
);
查询:
admin
getAdmins
login
结果:
"data":
"admin": null
如果我在 RootQuery 的 admin 字段中更改了返回值:
import GraphQLList, GraphQLString, GraphQLID, GraphQLObjectType, GraphQLSchema from 'graphql';
import AdminModel from '../models/Admin.model';
const AdminType = new GraphQLObjectType(
name: 'AdminType',
fields:
_id: type: GraphQLID ,
login: type: GraphQLString ,
password: type: GraphQLString
);
const AdminRooteType = new GraphQLObjectType(
name: 'AdminRooteType',
fields:
getAdmins:
type: new GraphQLList(AdminType),
resolve()
return AdminModel.find()
)
export default new GraphQLSchema(
query: new GraphQLObjectType(
name: 'RootQuery',
fields:
admin:
type: AdminRooteType,
#resolve() #
#// RETURN ANYTHING HERE:#
# return 'foobar'#
)
);
我得到了预期的结果:
"data":
"admin":
"getAdmins": [
"login": "123"
,
"login": "12asdf3"
]
这个问题的正确解决方案是什么? (不使用虚拟值作为回报)
非常感谢!
【问题讨论】:
【参考方案1】:您看到的是预期的行为。想象一下,我们有一个带有一些字段的 User
类型:
const UserType = new GraphQLObjectType(
name: 'User',
fields:
id: type: GraphQLID ,
name: type: GraphQLString ,
)
还有一种获取单个用户的方法:
const QueryType = new GraphQLObjectType(
name: 'Query',
fields:
user:
type: AdminRooteType,
resolve: () => getUser(),
,
,
)
如果getUser
返回一个表示User
的对象,则将调用所有字段的解析器(即User
类型上的id
和name
。
当这些字段(以及它们可能拥有的任何子字段)解析时,您最终会得到一个用户对象,以便整个 user
字段返回。响应可能类似于:
"data":
"user":
"id": 1,
"name": "Maria",
"comments": [
"id": 1,
// and so on...
]
现在,考虑当找不到用户而我们返回 null 时会发生什么。我们的响应如下所示:
"data":
"user": null
为 User 字段调用任何解析器是没有意义的。在这种情况下,您是否希望 API 仍返回 id
或 name
?如果是这样,这些字段将具有什么值?如果我们只返回一个空的id
和name
,客户端如何将该对象与存在但确实具有id
和name
空值的用户区分开来?
关键是,如果一个字段返回一个 GraphQLObjectType 并且它解析为 null,则不会调用 GraphQLObjectType 上的任何解析器。
通过将 getAdmins
字段不必要地嵌套在另一个 GraphQLObjectType 中,您不得不在 admin
的解析器中返回某种对象。因此,您需要忍受这种情况,或者完全避免创建AdminRootType
,而只需按照约定将getAdmins
字段直接放在您的查询类型上:
const QueryType = new GraphQLObjectType(
name: 'Query',
fields:
getAdmins:
type: new GraphQLList(AdminType),
resolve: () => AdminModel.find(),
,
,
)
【讨论】:
非常感谢,丹尼尔!主要思想是按类型(管理员、文章、订阅者等)对我的查询和突变进行分组。我认为这是让我的结构更清晰以上是关于对 GraphQL 中嵌套类型的深度查询返回 NULL的主要内容,如果未能解决你的问题,请参考以下文章