I am building a GraphQL Server with Apollo. And I am experiencing performance issues caused by the precedence of my resolvers.
I have a child type that is resolved on a parent type. Apollo Server decides to use the child type resolver instead of the much faster resolver on the parent type.
Query
query getAdGroup($id:ID!) {
AdGroup(id:$id) {
id
name
Keywords {
id
bid
term
}
}
}
Setup
AdGroupType (Parent)
type AdGroup {
id
name
keywords(filter: Filter): [Keyword]
}
Keyword Type (Child)
type Keyword {
id
term
bid
}
AdGroupResolver.js
// this gets executed
const getKeywords = (handler, adGroupId, filter) => handler.knex.raw(`
select
id,
term,
bid
from keyword
where adGroupId = ${adGroupId}
`);
export default {
Query: {
AdGroup: (parent, { id: adGroupId }, { handler }) => getAdGroup(handler, id),
},
AdGroup: {
Keywords: ({ id: adGroupId }, { filter }, { handler }) => getKeywords( handler, adGroupId, filter),
}
};
KeywordResolver.js
// this gets executed as well
const getKeywordTerm = (handler, keywordId) => handler.knex.raw(`
select
term
from keyword
where keywordId = ${keywordId}
`);
// this gets executed as well
const getKeywordBid = (handler, keywordId) => handler.knex.raw(`
select
bid
from keyword
where keywordId = ${keywordId}
`);
export default {
Query: {
Keyword: (parent, { id: keywordId }, { handler }) => getKeyword(handler, keywordId),
},
Keyword: {
term: ({ id: keywordId }, _, { handler }) => getKeywordTerm(handler, keywordId),
bid: ({ id: keywordId }, _, { handler }) => getKeywordBid(handler, keywordId),
}
};
The response time asking for 1000+ keywords on an Ad Group is very long.
But if I remove the term and bid functions on the Keyword resolver, the performance is much better because the values from the Keyword function in the Ad Group resolver are used.
How can I design my schema or configure Apollo to maintain this flexibility while not unnecessarily resolving each Keyword individually when I ask for the AdGroups keywords?