Javascript 如何在GraphQL中解析来自多个数据源的字段
关于设置GraphQL的初学者问题。我正在努力找到正确的方法,以最有效的方式为我的模式设置解析器。 假设在我的模式中有一个用户类型。一些字段在一个后端api中解析,其他字段在另一个后端api中解析Javascript 如何在GraphQL中解析来自多个数据源的字段,javascript,graphql,Javascript,Graphql,关于设置GraphQL的初学者问题。我正在努力找到正确的方法,以最有效的方式为我的模式设置解析器。 假设在我的模式中有一个用户类型。一些字段在一个后端api中解析,其他字段在另一个后端api中解析 type User { name: String address: String dateOfBirth: String department: String function: String manager: String } 姓名、地址和出生日期来自基础管理,
type User {
name: String
address: String
dateOfBirth: String
department: String
function: String
manager: String
}
姓名、地址和出生日期来自基础管理,其他字段来自组织数据库。
假设这是我的解析器:
Query {
User(parent, args, ctx) {
return {
name: '....',
address: '...',
dateOfBirth: '.....'
}
}
}
和特定子字段的解析程序:
User {
department(parent, args, ctx) {
}
function(parent, args, ctx) {
}
manager(parent, args, ctx) {
}
}
如果用户请求所有字段,这将导致4个请求。最后三个请求可能是一个一次性获取所有字段的请求。我当然希望有两个请求:一个请求基本信息,一个请求组织API。这可能会导致这种模式:
type User {
name: String
address: String
dateOfBirth: String
organisation: Organisation
}
type Organisation {
department: String
function: String
manager: String
}
以及子字段的解析程序:
User {
organisation {
return {
department: '...',
function: '...'
manager: '...'
}
}
}
现在对组织API的请求只被请求一次。然而,模式看起来很奇怪:这些字段应该是子对象的一部分。例如,如果我们要将manager数据移动到它自己的API中,那么如果我们将其移出子对象组织,模式就会中断。
我尝试用dataloader解决这个问题,但是在尝试了一些代码示例之后,我认为dataloader更多的是关于n+1问题,围绕相同对象类型的键,而不是批处理不同的字段。
那么,正确的方法是什么呢?在父解析程序上解析(返回)的内容将传播到子解析程序。因此,在User中,您可以执行以下操作:
查询{
用户(父级、参数、ctx){
//在此处调用返回组织字段的API
const organization=getOrganizationFields();
返回{
……组织
姓名:‘……’,
地址:“…”,
出生日期:‘……’
}
}
}
然后在子冲突解决程序(字段冲突解决程序)上显示可用信息,因此您可以执行以下操作:
用户{
部门(家长、args、ctx){
返回上级部门
}
经理(父级、参数、ctx){
返回parent.manager
}
}
一些实现,如graphqljs
使这些“统一”解析器隐式,因此您不必编写它们。当然,如果要批处理/缓存API请求,应该使用DataLoader
这可能会导致这种模式:
type User {
name: String
address: String
dateOfBirth: String
organisation: Organisation
}
type Organisation {
department: String
function: String
manager: String
}
以及子字段的解析程序:
User {
organisation {
return {
department: '...',
function: '...'
manager: '...'
}
}
}
现在对组织API的请求只被请求一次
您正沿着正确的方向走在一条很好的道路上,因为在一般情况下,graphql只允许您请求所需的内容
Albert的[user level resolver]对于一个数据源(一个带连接的SQL请求)的过度抓取可能是正确的
然而,模式看起来很奇怪:这些字段应该是子对象的一部分
当然,但这并不意味着不能用这种方式解决
例如,如果我们要将manager数据移动到它自己的API中
如果我们将模式移出子对象组织,它将被破坏
是的。。。也许你应该有更多的结构模式
您可能:
- 使用现有服务/BE透视图查看此模式李>
- 将破坏性更改/API版本控制问题混入此上下文中李>
type User {
name: String
address: String
dateOfBirth: String
role: Role
}
type Role {
organisation: Organisation
function: String
}
type Organisation {
department: String
manager: User
}
。。。假设每个用户只有一个角色。。。否则使用数组
在这种情况下,角色
和组织
子对象可以通过对组织服务-yust的一次调用来解决
return {
function: "team lead",
organisation: {
id: "someDeptID",
department: "some",
}
}
。。。如果查询需要
经理
字段,则它将(应该)由组织.经理
解析程序解析。当然,如果数据已经获取/可用,您可以在那里返回它(在role
resolver中)。在User的resolver上,它必须返回一个User类型的对象,只需在那里进行两个API调用并组成返回的对象。然后,此用户对象将传播到子解析程序,子解析程序将已解析,因此您只需从父解析程序获取字段并返回它(某些规范默认情况下会这样做,因此您可以忽略每个字段上的解析程序)@AlbertAlises-问题是,不同的字段部门、职能部门和经理,您希望这些调用是一个sep.api调用,只在客户机请求时执行。这将建议将它们放在一个单独的子字段中,以便对它们进行分组,或者为所有字段指定解析程序。在第一种情况下,您将根据字段解析的方式进行建模,我认为这不是好的做法。第二个选项是prefferable,但是每个请求的字段都会导致单独的api调用。因此,我需要对请求的字段进行批处理,从而生成1个api调用。