You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 17:36:06