Hasura环境下GraphQL订阅如何同时获取通知数据与聚合计数?
问题根因
你遇到的报错是Hasura GraphQL服务的原生限制:所有Subscription仅支持声明1个顶层查询字段。这个设计是为了简化订阅事件的触发判定逻辑——如果一个订阅绑定多个顶层字段,服务端需要监听多组数据表的变更事件,很容易出现触发逻辑冲突、推送重复数据或者性能损耗的问题,所以Hasura从底层就禁止了单订阅多顶层字段的写法。
可选解决方案
有三种成熟的实现方式可以满足你的需求,你可以根据业务场景选择:
1. 拆分为两个独立订阅(最推荐)
分别创建通知列表、通知计数两个独立订阅,在前端用react-apollo-client同时发起即可。两个订阅都使用相同的userId过滤条件,数据库新增通知时两个订阅会几乎同时触发,用户感知不到差异,也不需要额外的逻辑处理。
示例代码如下:
// 通知列表订阅 const GET_NOTIFICATION_LIST = gql` subscription($userId: Number!) { notifications(where: { user_id: { _eq: $userId } }) { creation_time description } } ` // 通知计数订阅 const GET_NOTIFICATION_COUNT = gql` subscription($userId: Number!) { notifications_aggregations (where: { user_id: { _eq: $userId } }) { aggregate { count } } } `
2. 前端自行统计数量(适合小数据量场景)
如果你的通知列表是全量返回、没有分页逻辑,完全可以只保留通知列表的订阅,每次订阅返回新数据时,直接取返回数组的length属性作为总数量即可,逻辑更简洁,也减少了服务端的订阅连接开销。
3. 数据库自定义视图封装(适合复杂聚合场景)
如果后续需要同时返回更多关联的聚合结果,可以先在PostgreSQL中创建一个封装了通知明细和对应聚合数据的自定义视图,再针对这个视图创建订阅,就能在单个订阅的顶层字段下拿到所有需要的字段,不过这个方案需要修改数据库结构,改造成本相对更高。
内容的提问来源于stack exchange,提问作者Itamar Smirra
相关产品推荐
相关产品推荐

