能否通过ID以外的字段查询Apollo缓存中的数据?
可以通过对象ID以外的字段查询Apollo缓存,以下是两种常用的实现方式:
方案1:配置字段策略实现本地查询(推荐)
你可以通过配置Apollo缓存的typePolicies新增一个纯本地的查询字段,无需后端提供对应接口,即可直接通过otherId从缓存读取对应Record对象。
首先在初始化ApolloClient时配置字段策略:
import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; const cache = new InMemoryCache({ typePolicies: { Query: { fields: { // 新增自定义本地查询字段 recordByOtherId: { read(_, { args, cache, toReference }) { // 遍历缓存中所有Record类型对象匹配otherId const cachedRecords = cache.extract().Record || {}; const matched = Object.values(cachedRecords).find( record => record.otherId === args.otherId ); return matched ? toReference(matched) : null; } } } } } }); const client = new ApolloClient({ cache, // 其他Apollo配置 uri: '你的GraphQL接口地址' });
业务代码中直接调用该本地查询即可,需要加@client指令标记该字段走本地缓存逻辑:
# 定义查询语句 const GET_RECORD_BY_OTHER_ID = gql` query GetRecordByOtherId($otherId: String!) { recordByOtherId(otherId: $otherId) @client { id otherId # 其他需要的Record字段 } } `; // 调用查询 const { data } = await client.query({ query: GET_RECORD_BY_OTHER_ID, variables: { otherId: '你要查询的otherId值' } }); const targetRecord = data.recordByOtherId;
性能优化(数据量大时推荐)
如果Record数量较多,每次查询遍历缓存会影响性能,可以在拉取records列表时预构建索引,查询时直接取索引即可:
const cache = new InMemoryCache({ typePolicies: { Query: { fields: { records: { merge(existing = [], incoming, { readField, toReference }) { // 初始化索引存储 if (!cache._otherIdIndex) cache._otherIdIndex = new Map(); // 新增记录时同步写入索引 incoming.forEach(record => { const otherId = readField('otherId', record); cache._otherIdIndex.set(otherId, toReference(record)); }); return incoming; } }, recordByOtherId: { read(_, { args }) { return cache._otherIdIndex?.get(args.otherId) || null; } } } } } });
注意:如果有更新、删除
Record的业务场景,需要同步维护该索引,避免返回脏数据。
方案2:临时全量读取过滤
如果只是极少数场景需要查询,不想新增缓存配置,可以直接从缓存读取全量records列表后过滤:
const GET_ALL_RECORDS = gql` query GetAllRecords($someQueryParam: String!) { records(someQueryParam: $someQueryParam) { id otherId } } `; // 从缓存读取已拉取的全量records const { records } = client.readQuery({ query: GET_ALL_RECORDS, variables: { someQueryParam: '对应请求参数' } }); // 过滤得到目标记录 const targetRecord = records.find(r => r.otherId === '目标otherId');
内容的提问来源于stack exchange,提问作者Stanley Ayzenberg
相关产品推荐
相关产品推荐

