Apollo Client订阅updateQuery不遵循where参数问题求助
解决Apollo Client订阅更新不遵循过滤条件的问题
核心问题分析
你遇到的问题本质是:Apollo Client的订阅更新默认不会自动继承主查询的过滤规则,updateQuery若不手动处理就会混入不符合条件的项;依赖默认缓存更新时,只会修改已有项、无法添加新项——这是因为缓存字段策略未正确关联where参数,导致新项无法匹配到对应的查询缓存条目。
解决方案步骤
1. 优化类型策略的Merge逻辑
offsetLimitPagination的默认实现未严格根据where参数区分缓存条目,需自定义merge函数,确保只有符合当前查询where条件的项才会被合并到缓存中。
修改你的类型策略:
typePolicies: { Query: { fields: { process: { keyArgs: ["where", "order_by"], // 明确用这两个参数区分不同缓存条目 merge(existing, incoming, { args }) { if (!existing) return incoming; // 过滤incoming中符合当前where条件的项 const filteredIncoming = incoming.filter(item => { // 根据你的where结构实现匹配逻辑,示例为检查deleted状态 return !item.deleted && matchesWhere(item, args.where); }); // 去重合并:保留existing中未被覆盖的项,加上过滤后的incoming const existingIds = new Set(existing.map(p => p.id)); const merged = [...existing.filter(p => !filteredIncoming.some(i => i.id === p.id)), ...filteredIncoming]; // 按updated_at排序(按需调整) return merged.sort((a, b) => new Date(a.updated_at) - new Date(b.updated_at)); }, read(existing = []) { return uniqueByRef(existing); }, }, process_stream: { keyArgs: ["where"], merge(existing, incoming) { // 订阅流仅做去重,主查询的process字段处理过滤逻辑 if (!existing) return incoming; const existingIds = new Set(existing.map(p => p.id)); return [...existing, ...incoming.filter(i => !existingIds.has(i.id))]; }, }, }, }, // 确保单条Process数据的缓存更新正确 Process: { keyFields: ["id"], }, }
注:需实现matchesWhere函数,根据你的where参数结构(如_and、_eq等操作符)验证项是否符合条件。
2. 简化订阅的updateQuery
无需在updateQuery中手动过滤,让Apollo利用缓存策略自动处理。调整subscribeToMore,使订阅变量与主查询过滤条件一致:
const { cache } = useApolloClient(); subscribeToMore({ document: STREAM_PROCESS, variables: { where: filters.where, // 直接复用主查询的where参数 cursor: { initial_value: { updated_at: cursor }, ordering: "ASC" }, }, updateQuery: (prev, { subscriptionData }) => { setCursor(new Date().toISOString()); if (!subscriptionData.data) return prev; // 借助缓存的merge逻辑自动处理合并与过滤 cache.writeQuery({ query: QUERY_PROCESS, variables: { ...filters, limit }, data: { process: [...prev.process, ...subscriptionData.data.process_stream], }, }); return { ...prev }; }, });
3. 确保服务端订阅返回符合过滤条件的项
优先在服务端调整PROCESS_STREAM的Resolver,确保只返回符合where参数的项——这样客户端无需额外过滤,减少前端逻辑负担。
关键注意点
keyArgs必须包含where,让Apollo根据不同过滤条件维护独立缓存条目,避免结果混淆。- 自定义merge时务必先过滤incoming项,确保只有符合当前查询条件的内容被合并。
- 订阅变量需与主查询变量完全一致,保证缓存能匹配到对应条目。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

