我可能面临 Apollo GraphQL server 的设计限制我想问一下是否有解决方法。
我的架构包含类型 Thing
,具有字段 flag
.我希望能够过滤 things
通过 flag
的值,但如果单独解析该字段似乎是不可能的。如果我想排序 things
也会出现同样的问题.这是一个例子:
type Thing {
id: String!
flag Boolean!
}
type Query {
things(onlyWhereFlagIsTrue: Boolean): [Thing!]!
}
const resolvers = {
Thing: {
flag: async ({id}) => {
const value = await getFlagForThing(id);
return value;
}
},
Query: {
async things(obj, {onlyWhereFlagIsTrue = false}) {
let result = await getThingsWithoutFlags();
if (onlyWhereFlagIsTrue) {
// ↓ this does not work, because flag is still undefined
result = _.filter(result, ['flag', true]);
}
return result;
}
}
}
有什么过滤方法
things
在所有异步字段都解决之后?我知道我可以调用getFlagForThing(id)
里面 things
解析器,但这不是重复我自己吗?解析 flag
背后的逻辑可能比仅调用一个函数要复杂一些。更新:这是迄今为止我能找到的最好的解决方案。非常丑陋且难以扩展到其他领域:
const resolvers = {
Thing: {
flag: async ({id, flag}) => {
// need to check if flag has already been resolved
// to avoid calling getThingsWithoutFlags() twice
if (!_.isUndefined(flag)) {
return flag;
}
const value = await getFlagForThing(id);
return value;
}
},
Query: {
async things(obj, {onlyWhereFlagIsTrue = false}) {
let result = await getThingsWithoutFlags();
if (onlyWhereFlagIsTrue) {
// asynchroniously resolving flags when needed
const promises = _.map(result, ({id}) =>
getFlagForThing(id)
);
const flags = await Promise.all(promises);
for (let i = 0; i < flags.length; i += 1) {
result[i].flag = flags[i];
}
// ↓ this line works now
result = _.filter(result, ['flag', true]);
}
return result;
}
},
};
最佳答案
我认为这里的问题实际上并不是 Apollo 服务器的限制,而更多地与您有一个带有解析器的原始字段这一事实有关。通常,最好仅在该字段将返回单独的类型时才对字段使用解析器:
Thing {
id: ID!
flag: Boolean!
otherThings: OtherThing
}
Query {
things(onlyWhereFlag: Boolean): [Thing!]!
}
在此示例中,可以为
otherThings
设置单独的解析器。 ,但是如果一个字段是一个原始字段,那么我只会将该字段与 Thing 一起解析。使用您的原始架构:
const filterByKeyValuePair = ([key, value]) => obj => obj[key] === value;
const resolvers = {
Query: {
async things(parent, { onlyWhereFlag }) {
const things = await Promise.all(
(await getThings()).map(
thing =>
new Promise(async resolve =>
resolve({
...thing,
flag: await getFlagForThing(thing)
})
)
)
);
if (onlyWhereFlag) {
return things.filter(filterByKeyValuePair(['flag', true]));
} else {
return things;
}
}
}
};
如果
flag
不是原始人吗?好吧,如果您想按它进行过滤,那么您将有几个不同的选择。这些选项实际上取决于您获取“标志”数据的方式。如果您可以提供有关您的架构和数据模型的更多详细信息,我将很乐意详细说明。
关于graphql - Apollo GraphQL 服务器 : filter (or sort) by a field that is resolved separately,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46619596/