由于某些原因,我很难弄清楚如何为GraphQL接口和实现该接口的类型组合解析器。
说我有以下模式:
interface IPerson {
id: ID!
firstName: String!
lastName: String!
}
type ClubMember implements IPerson {
...IPerson fields
memberType: String!
memberSince: DateTime!
}
type StaffMember implements IPerson {
...IPerson fields
hireDate: DateTime!
reportsTo: StaffMember
}
extend type Query {
people(ids: [Int!]): [IPerson]
}
包含所有字段的完整ClubMember
查询,例如:
query {
people(ids: [123456,234567,345678]) {
id
firstName
lastName
... on ClubMember {
memberType
memberSince
}
}
}
将产生如下响应:
[
{
"id": 123456,
"firstName": "Member",
"lastName": "McMemberface",
"memberType": "VIP",
"memberSince": "2019-05-28T16:05:55+00:00"
},
...etc.
]
我已将makeExecutableSchema()
中的apollo-server
与inheritResolversFromInterfaces: true
一起使用,并且我希望能够通过让模型类支持{{ 1}},IPerson
等返回仅具有与每种类型相关的字段的对象,即ClubMember
的模型类仅获取IPerson
等所需的字段。 ,上面的响应将执行2条SQL语句:
IPerson
和
SELECT id, firstName, lastName FROM Contacts WHERE id IN(?);
当然,我可以通过在数据库级别执行JOIN来在一条SQL语句中获取所有数据,但我确实希望有一种(只有一种)方式来解决SELECT contactId, memberType, memberSince FROM Members WHERE contactId IN(?);
所需的字段,并让其他类型的数据使用自己的解析器来扩充该数据。
我的问题是,我是否需要自己在IPerson
查询类型的解析器中将结果对象“连接”在一起?例如
people
或者阿波罗有什么办法可以为我们处理这个问题?我想要类似apollo-resolvers
的东西吗? docs on unions and interfaces并不是超级有帮助;我在const resolvers = {
Query: {
people: function( parent, args, context, info ) {
let persons = context.models.Person.getByIds( args.ids );
let members = context.models.Member.getByIds( args.ids );
/*
return an array of {...person, ...member} where person.id === member.id
*/
}
}
}
上有__resolveType
,但是文档未指定如何解析每种具体类型的字段。是否有更好的方法可以使用Dataloader或其他方法来实现此目标?
我认为this question与我的问题有关,因为如果查询不通过片段请求该类型的任何字段,我不想获取具体类型的数据。 Github上还有this issue。
非常感谢!
编辑:
IPerson
如下所示:
__resolveType
答案 0 :(得分:0)
这个问题确实不是特定于Apollo Server甚至是GraphQL的-查询多个表并获得一组结果,尤其是在处理多个数据模型时,将变得棘手。
当然,您可以分别查询每个表并合并结果,但这并不是特别有效。我认为到目前为止,处理这种情况的最简单方法是在数据库中创建视图,例如:
CREATE VIEW people AS
SELECT club_members.id AS id,
club_members.first_name AS first_name,
club_members.last_name AS last_name,
club_members.member_type AS member_type,
club_members.member_since AS member_since,
null AS hire_date,
null AS reports_to,
'ClubMember' AS __typename
FROM club_members
UNION
SELECT staff_members.id AS id,
staff_members.first_name AS first_name,
staff_members.last_name AS last_name,
null AS member_type,
null AS member_since,
staff_members.hire_date AS hire_date,
staff_members.reports_to AS reports_to
'StaffMember' AS __typename
FROM staff_members;
您也可以只使用一个表,但是视图允许您将数据保留在单独的表中并一起查询。现在,您可以为视图添加数据模型,并使用该模型查询所有“人员”。
注意:为方便起见,我在此处添加了__typename
列-通过返回__typename
,您可以省略指定自己的__resolveType
函数的作用-GraphQL将分配适当的类型在运行时为您服务。