GraphQL 为列表和详细查询共享相同的对象类型
Posted
技术标签:
【中文标题】GraphQL 为列表和详细查询共享相同的对象类型【英文标题】:GraphQL share same Object type for list and detail query 【发布时间】:2020-01-17 00:34:20 【问题描述】:我正在采用 GraphQL 作为多个后端微服务的数据组合层。我们有一个UserService
,它提供了一些与用户相关的REST API,一个是/users
,另一个是/detail?userId=$userId
。
我有以下架构定义:
type User
userId: ID!
name: String!
address: String
// ... some other fields
Query
users: [User]!
userDetail(userId: ID): User
问题是,出于某种性能原因,/users
中的 User
项的字段少于 /detail
。例如,address
字段不存在于 list API 中,而仅存在于 detail API 中。
那么,我们是否必须为 list 查询定义另一个 UserListItem
?由于后端 API 的限制,我们不能在 list 和 detail 查询之间共享相同的 User
类型定义。
【问题讨论】:
【参考方案1】:首先,我认为我们应该考虑一下为什么列表API中不存在地址字段?
在 Apollo 看来,相同的用户 id 应该得到相同的结果。 所以在你的情况下,这是不合理的。
如果不为列表查询定义其他类型将导致缓存问题(客户端)
您可以参考这篇文章了解更多信息
(相同的id,输入不同的结果)
https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching
如果你为列表查询定义另一种类型也会导致缓存问题(关于客户端在变异后更新缓存)
当然,客户端可以通过设置 fetchPolicy 或手动更新缓存来解决缓存问题,但这并不是最好的解决方案。
所以如果我是后端开发人员,我会尝试将地址字段放入列表 API。
如果你真的不能把地址字段放在列表API中,我认为定义另一种类型会更好。
但是客户端需要更加注意更新缓存的问题。
例如,如果我们为用户定义另一种类型。 (输入UserDetail
)
假设我们有一个显示用户列表的页面(输入User
),并且我们有一个修改用户信息的突变。
通常,当我们进入编辑页面时,我们会执行userDetail
来初始化表单数据。(输入UserDetail
)
如果突变后返回类型为User
,则用户列表中具有相同ID的用户将自动更新缓存。
(https://www.apollographql.com/docs/react/advanced/caching/#automatic-cache-updates)
但是当我们回到编辑页面时,你会发现 userDetail 的数据在突变后保持不变,因为突变的返回类型是 User
而不是 UserDetail
。
在这种情况下,我会将 fetchPolicy 设置为network-only
(userDetail 查询),反之亦然。
相同的ID和类型,但不同的结果
参考这篇文章
https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching
【讨论】:
感谢您的回复。 REST API 由其他后端开发人员管理。为什么 list API 中不存在address
或其他一些字段,通常它与性能有关。也许所有的User
数据都被分成TWO 数据库tables:一个表只保存一些简短的数据,另一个表包含更多的用户详细信息。通过将用户数据拆分成两张表,我们可以更快地读写 mysql。而当我们需要向用户展示list时,我们只需要从ONE表中SELECT
,不需要加入另一个明细表。
@Jess 我了解您的情况,我更新了我的回答,描述了客户端可能遇到的问题。我不知道什么是最好的解决方案,所以我只是分享我的经验。对不起我的英语不好,希望你能明白我想表达的意思。
再次感谢您的体验。我从你的回答中学到了很多。顺便说一句,我认为你的英语很好以上是关于GraphQL 为列表和详细查询共享相同的对象类型的主要内容,如果未能解决你的问题,请参考以下文章
GraphQL漏洞案例:获取任何Facebook用户的朋友列表和部分支付卡详细信息