我正在用Apollo构建GraphQL服务器。 而且我遇到了由解析器的优先级引起的性能问题。
我有一个在父类型上解析的子类型。 Apollo Server决定使用子类型的解析器,而不是父类型的解析器。
query getAdGroup($id:ID!) {
AdGroup(id:$id) {
id
name
Keywords {
id
bid
term
}
}
}
type AdGroup {
id
name
keywords(filter: Filter): [Keyword]
}
type Keyword {
id
term
bid
}
// 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),
}
};
// 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),
}
};
在广告组中要求1000个以上的关键字的响应时间很长。
但是,如果我删除了关键字解析器上的术语和出价功能,则性能会好得多,因为使用了广告组解析器中关键字功能的值。
当我请求AdGroups关键字时,如何设计我的架构或配置Apollo来保持这种灵活性,同时又不必不必要地单独解析每个关键字?
答案 0 :(得分:0)
在GraphQL中,解析 every 字段,并且始终在子字段之前解析父字段(因为将父值传递给子字段的解析器)。如果您不提供解析器,则GraphQL使用默认的解析器函数尝试在父值上找到匹配的属性(有关详细说明,请参见this answer)。如果您提供解析器,则每次响应中存在该字段时,解析器就会始终运行(对于列表中的每个项目,该列表中的每个项目都将始终运行)。
在某些情况下,有时父字段已经提供了您要解析的值,而有时却没有,您可以简单地向解析器添加条件:
export default {
Keyword: {
term: ({ id: keywordId, term }, _, { handler }) => term || getKeywordTerm(handler, keywordId),
bid: ({ id: keywordId, bid }, _, { handler }) => bid || getKeywordBid(handler, keywordId),
}
};