Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在GraphQL中解析来自多个数据源的字段_Javascript_Graphql - Fatal编程技术网

Javascript 如何在GraphQL中解析来自多个数据源的字段

Javascript 如何在GraphQL中解析来自多个数据源的字段,javascript,graphql,Javascript,Graphql,关于设置GraphQL的初学者问题。我正在努力找到正确的方法,以最有效的方式为我的模式设置解析器。 假设在我的模式中有一个用户类型。一些字段在一个后端api中解析,其他字段在另一个后端api中解析 type User { name: String address: String dateOfBirth: String department: String function: String manager: String } 姓名、地址和出生日期来自基础管理,

关于设置GraphQL的初学者问题。我正在努力找到正确的方法,以最有效的方式为我的模式设置解析器。 假设在我的模式中有一个用户类型。一些字段在一个后端api中解析,其他字段在另一个后端api中解析

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版本控制问题混入此上下文中
。。。但是你已经可以定义“正确的模式”,f.e

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调用。