Apollo如何生成有意义的__typename?结合Hasura排查全为Query问题
所有返回结果的__typename统一为Query,核心原因是前端拿到的业务对象本质都是GraphQL根Query类型的实例,而非对应表/业务实体类型的实例,不存在Hasura Schema生成不完整的问题,直接按以下优先级排查即可。
排查维度(按问题出现概率从高到低排序)
中间Apollo Server层的Resolver返回逻辑错误
你当前架构是Hasura作为上游数据源、Apollo Server作为BFF层对接前端时,最常见的错误是没有从Hasura的完整查询响应中提取对应业务字段的子对象,直接把整个根Query层级的响应对象透传给了前端。
参考反例代码:// 错误返回逻辑:直接把整个Hasura查询的根对象返回 resolvers: { Query: { fetchFollowedArtist: async (_, args, { hasuraClient }) => { // 该调用的返回结构是 { data: { users_performers_by_pk: {...} } } return await hasuraClient.query({ query: FETCH_FOLLOWED_ARTIST, variables: args }) } } }正确返回逻辑需要从响应中取出真正的表实体对象:
resolvers: { Query: { fetchFollowedArtist: async (_, args, { hasuraClient }) => { const res = await hasuraClient.query({ query: FETCH_FOLLOWED_ARTIST, variables: args }) return res.data.users_performers_by_pk // 提取真实表类型对象返回 } } }这种错误下,前端拿到的每个“业务字段”实际都是根Query类型的引用,自动附加的__typename自然全为Query。
前端Apollo Client的结果解析逻辑错位
检查useQuery拿到返回值后的取值路径:- 如果直接把整个
data对象当成业务实体做遍历渲染,没有往下取对应嵌套的表字段层,你操作的对象本质就是根Query类型,__typename自然为Query - 检查自定义的
dataIdFromObject配置,有没有因为取值路径错误,把所有实体的主键都绑定到根Query的缓存条目下,导致缓存读取时统一附加了Query的__typename
- 如果直接把整个
Hasura侧的返回结果校验
直接绕过中间Apollo层,打开Hasura自带的GraphiQL控制台,原样运行你写的FetchFollowedArtist查询:- 如果控制台返回结果里的__typename是正确的
users_performers,可以完全排除Hasura的问题,回头检查中间Apollo层的逻辑 - 如果控制台返回的__typename本身就是Query,检查Hasura的元数据缓存:修改表结构后如果没触发Schema重建,会出现类型映射错乱的问题,手动在控制台触发一次Schema刷新即可
- 同时检查当前使用角色对
users_performers表的Select权限,确认权限规则没有错误拦截行记录的返回,导致Hasura返回空的根对象占位
- 如果控制台返回结果里的__typename是正确的
Apollo层的Schema缝合配置错误
如果是用Apollo Gateway做多源Schema缝合,检查Hasura源的类型映射配置:如果原本属于users_performers类型的字段没有正确和缝合后的Schema做映射,被错误挂到根Query类型下,GraphQL引擎会默认把这些字段的返回值识别为Query类型,附加对应__typename。
注意:Apollo客户端自动附加__typename是默认的标准化行为,只要返回对象本身的类型映射正确,就会自动带出对应业务类型的值,不需要手动修改客户端配置。
内容的提问来源于stack exchange,提问作者Amantel

