如何构造GraphQL查询,使默认返回[Interface]的结果仅保留A类型并过滤空对象?
如何在GraphQL中过滤接口集合,仅返回指定类型的实例
嘿,这个问题我之前处理过!要实现只返回A类型实例、过滤掉B类型和空对象的需求,仅靠客户端的查询语法没法让服务器自动过滤,但有两种靠谱的解决方案,分别从后端和客户端层面入手:
方案1:后端加过滤参数(推荐,最彻底)
最直接的方式是让后端支持类型过滤,这样服务器直接返回你要的结果,不用客户端再额外处理。
具体操作:
- 先修改GraphQL的Schema,给返回接口集合的
q字段加个过滤参数:
type Query { # 新增filterType参数,用来指定要返回的类型 q(filterType: String): [Interface!]! } interface Interface { common: String! } type A implements Interface { common: String! foo: String! } type B implements Interface { common: String! bar: String! }
然后在
q字段的Resolver里写过滤逻辑:
比如当传入filterType: "A"时,就只返回A类型的实例,把B类型的都筛掉。最后客户端发起带参数的查询:
query { q(filterType: "A") { ... on A { foo } } }
这时候服务器返回的结果就只有A类型的实例,不会出现B或者空对象了。
方案2:客户端拿到结果后过滤
如果没法修改后端,那就在客户端拿到数据后自己处理,利用GraphQL自带的__typename字段来区分类型。
步骤:
- 修改查询,把
__typename加上(所有GraphQL类型都会默认返回这个字段,用来标识对象的具体类型):
query { q { __typename ... on A { foo } } }
返回的结果会是这样的:
{ "data": { "q": [ { "__typename": "A", "foo": "foo" }, { "__typename": "B" } ] } }
- 用客户端代码过滤:
比如用JavaScript的话,直接过滤掉__typename不是"A"的条目就行:
const filteredItems = data.q.filter(item => item.__typename === "A");
这样就得到了纯A类型的数组。
为啥原查询会返回空对象?
这里得解释下:GraphQL的规范要求,当查询接口类型的集合时,服务器要返回所有符合该接口的实例。如果你的查询只请求了A类型的字段(比如... on A { foo }),那B类型的实例因为没有匹配的字段请求,就会返回空对象——要是你同时请求了接口的公共字段common,那B类型实例会返回common的值,而不是空对象。
内容的提问来源于stack exchange,提问作者Ákos Vandra-Meyer
相关产品推荐
相关产品推荐

