在 GraphQL 中,如何实现可选查询?
In GraphQL, how do I implement optional queries?
编辑:由于似乎不清楚,我特别询问我应该在解析函数内为后端查询进行的数据库请求。
我正在实施 GraphQL 查询,但我无法准确理解在给定查询中我应该进行多少次调用。例如,这是一个包含用户和用户可以加入的俱乐部的数据结构:
User {
UserID
Clubs
OtherStuff
}
Club{
ClubID
ClubName
}
我可以对我的数据库进行以下调用:
- 获取所有用户ID
- 获取 UserID 的信息
- 获取用户的所有 ClubID
- 获取 ClubID 的信息
我不明白的是我是否应该在每次查询用户时都进行所有这些调用。如果有人只查询 UserID,那么检索其他所有内容似乎是一种巨大的浪费。 Clubs for User 应该是一个完全独立的 GraphQL 查询,Clubs 应该只有 return ClubID,还是有一种方法可以有效地允许完整的 Club 信息在 Clubs 字段中可用?
编辑 2:
好的,这是我的代码。我已经评论了我不确定该怎么做的部分。
const QueryType = new GraphQLObjectType({
name: 'Query',
fields: {
User: userQueryField,
Club: clubQueryField
}
});
const clubQueryField = {
type: new GraphQLList(ClubType),
args: {
UserID: {
description: 'Returns all clubs the user is a part of',
type: GraphQLID
}
},
resolve(root, {UserID}) {
//.....
}
};
const userQueryField = {
type: new GraphQLList(UserType),
args: {
UserID: {
description: 'If omitted, returns a list of all users. \
Otherwise, returns the user with the provided ID',
type: GraphQLID
}
},
resolve(root, {UserID}) {
if(UserID){
return new Promise((resolve, reject) => {
getUserInfo(UserID, function(response){
//HERE: I have tried different things, like clubQueryField(UserID) and clubQueryField.resolve, but with no luck
UserID.Clubs = clubQueryField
resolve([response]);
});
});
}
}
};
编辑 3:用户类型定义。
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
UserID: {
type: GraphQLID
},
Clubs: {
type: new GraphQLList(ClubType)
}
})
});
GraphQL 具有延迟加载功能,可以处理查询中的其他字段。如果用户编写以下查询:
query{
users{
id
}
}
它获取用户 ID 并且显然不寻找其他字段。不过,这绝对取决于您的解析器。如果您像这样编写解析器:users { resolve: body => get_user_id}
,它会从数据库中获取用户 ID。
希望这对您有所帮助!
GraphQL API 是根据类型和字段组织的,我建议为用户类型和俱乐部类型创建单独的查询,如果有人只查询用户 ID,他们将使用用户查询。
查询用户:
query {
users {
id
}
}
查询俱乐部:
query {
club {
clubID
clubName
userId
}
}
如果有人试图查询 users/club 您可以像这样将俱乐部类型添加到用户类型:
query {
users {
id
club {
clubID
clubName
}
}
}
在你的用户类型中会有一个名为 club 的字段,它将成为 club 类型,在解析器中它将使用 obj.userId
作为参数调用 club 查询,GraphQL 的美妙之处在于你让客户决定要获取哪些字段。
你可以看到一个嵌套查询的例子here
编辑:然后在您的情况下,您可以修改您的 userType 以包括用户所属的俱乐部,您在 clubQueryField
中不需要该条件,该条件将在客户进行的查询中,假设您的用户类型是这样的:
用户类型:
export default new GraphQLObjectType({
name: 'UserType',
fields: {
userId: {
description: 'user id',
type: GraphQLString
},
email: {
description: 'user email',
type: GraphQLString
},
clubs: {
description: 'User clubs',
type: new GraphQLList(ClubType),
resolve: (obj, args, _) => {
return getUserClubs(obj.userId);
}
},
}
});
那么如果您的客户端只需要用户,它将请求如下内容:
query {
User {
userId
email
}
}
如果客户需要用户和俱乐部,它会请求这样的东西:
query {
User {
userId
email
clubs {
field1
field2
}
}
}
编辑:由于似乎不清楚,我特别询问我应该在解析函数内为后端查询进行的数据库请求。
我正在实施 GraphQL 查询,但我无法准确理解在给定查询中我应该进行多少次调用。例如,这是一个包含用户和用户可以加入的俱乐部的数据结构:
User {
UserID
Clubs
OtherStuff
}
Club{
ClubID
ClubName
}
我可以对我的数据库进行以下调用:
- 获取所有用户ID
- 获取 UserID 的信息
- 获取用户的所有 ClubID
- 获取 ClubID 的信息
我不明白的是我是否应该在每次查询用户时都进行所有这些调用。如果有人只查询 UserID,那么检索其他所有内容似乎是一种巨大的浪费。 Clubs for User 应该是一个完全独立的 GraphQL 查询,Clubs 应该只有 return ClubID,还是有一种方法可以有效地允许完整的 Club 信息在 Clubs 字段中可用?
编辑 2: 好的,这是我的代码。我已经评论了我不确定该怎么做的部分。
const QueryType = new GraphQLObjectType({
name: 'Query',
fields: {
User: userQueryField,
Club: clubQueryField
}
});
const clubQueryField = {
type: new GraphQLList(ClubType),
args: {
UserID: {
description: 'Returns all clubs the user is a part of',
type: GraphQLID
}
},
resolve(root, {UserID}) {
//.....
}
};
const userQueryField = {
type: new GraphQLList(UserType),
args: {
UserID: {
description: 'If omitted, returns a list of all users. \
Otherwise, returns the user with the provided ID',
type: GraphQLID
}
},
resolve(root, {UserID}) {
if(UserID){
return new Promise((resolve, reject) => {
getUserInfo(UserID, function(response){
//HERE: I have tried different things, like clubQueryField(UserID) and clubQueryField.resolve, but with no luck
UserID.Clubs = clubQueryField
resolve([response]);
});
});
}
}
};
编辑 3:用户类型定义。
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
UserID: {
type: GraphQLID
},
Clubs: {
type: new GraphQLList(ClubType)
}
})
});
GraphQL 具有延迟加载功能,可以处理查询中的其他字段。如果用户编写以下查询:
query{
users{
id
}
}
它获取用户 ID 并且显然不寻找其他字段。不过,这绝对取决于您的解析器。如果您像这样编写解析器:users { resolve: body => get_user_id}
,它会从数据库中获取用户 ID。
希望这对您有所帮助!
GraphQL API 是根据类型和字段组织的,我建议为用户类型和俱乐部类型创建单独的查询,如果有人只查询用户 ID,他们将使用用户查询。
查询用户:
query {
users {
id
}
}
查询俱乐部:
query {
club {
clubID
clubName
userId
}
}
如果有人试图查询 users/club 您可以像这样将俱乐部类型添加到用户类型:
query {
users {
id
club {
clubID
clubName
}
}
}
在你的用户类型中会有一个名为 club 的字段,它将成为 club 类型,在解析器中它将使用 obj.userId
作为参数调用 club 查询,GraphQL 的美妙之处在于你让客户决定要获取哪些字段。
你可以看到一个嵌套查询的例子here
编辑:然后在您的情况下,您可以修改您的 userType 以包括用户所属的俱乐部,您在 clubQueryField
中不需要该条件,该条件将在客户进行的查询中,假设您的用户类型是这样的:
用户类型:
export default new GraphQLObjectType({
name: 'UserType',
fields: {
userId: {
description: 'user id',
type: GraphQLString
},
email: {
description: 'user email',
type: GraphQLString
},
clubs: {
description: 'User clubs',
type: new GraphQLList(ClubType),
resolve: (obj, args, _) => {
return getUserClubs(obj.userId);
}
},
}
});
那么如果您的客户端只需要用户,它将请求如下内容:
query {
User {
userId
email
}
}
如果客户需要用户和俱乐部,它会请求这样的东西:
query {
User {
userId
email
clubs {
field1
field2
}
}
}