По какой-то причине мне трудно понять, как объединить преобразователи для интерфейса 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
, и я хочу иметь возможность использовать средства разрешения по умолчанию для каждого интерфейса / типа, имея классы моделей, поддерживающие IPerson
, ClubMember
и т. Д., Возвращающие объекты только с полями, относящимися к каждомутип, т. е. класс модели для IPerson
выбирает только те поля, которые требуются для IPerson
и т. д. То есть приведенный выше ответ будет выполнять 2 оператора SQL:
SELECT id, firstName, lastName FROM Contacts WHERE id IN(?);
и
SELECT contactId, memberType, memberSince FROM Members WHERE contactId IN(?);
Конечно, я мог бы получить все данные в одном операторе SQL, выполнив JOIN на уровне базы данных, но я действительно хочу иметь один (и только один) способ разрешения полей, требуемых IPerson
, ипусть другие типы дополняют эти данныеУ них есть собственные распознаватели.
У меня такой вопрос, нужно ли мне самому "объединять" результирующие объекты в распознаватель для типа запроса people
?Например,
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
*/
}
}
}
Или Аполлон справляется с этим для нас?Хочу ли я что-то вроде apollo-resolvers
?Документы по объединениям и интерфейсам не очень полезны;У меня __resolveType
на IPerson
, но в документах не указано, как разрешаются поля для каждого конкретного типа.Есть ли лучший способ добиться этого с помощью Dataloader или другой подход?
Я думаю этот вопрос связан с моей проблемой, поскольку я не хочу получать данные дляконкретный тип, если запрос не запрашивает какие-либо поля этого типа через фрагмент.Есть также эта проблема на Github.
Большое спасибо!
Редактировать: __resolveType
выглядит следующим образом:
{
IPerson: {
__resolveType: function ( parent, context, info ) {
if ( parent.memberType ) {
return 'ClubMember';
}
...etc.
}
}
}