代码之家  ›  专栏  ›  技术社区  ›  Jakob Runge

使用Apollo缓存具有多个ID的GraphQL查询

  •  2
  • Jakob Runge  · 技术社区  · 6 年前

    我们正在web应用程序中使用apollo客户机,并正在寻找提高缓存使用率的方法。

    我们有一个以id数组为参数的查询 foo bar 会是这样的:

    query routes {
      routes(routeNames: ["foo", "bar"]) {
        items {
          name
          route
          defaults
        }
      }
    }
    

    缓存设置如下所示:

    export const cacheRedirects = {
      Query: {
        routes: (_: any, args: RoutesArgs, { getCacheKey }: Resolver<'name'>): Array<CacheKey> =>
          args.routeNames.map(name => getCacheKey({ __typename: 'Route', name })),
      },
    };
    
    export const dataIdFromObject = (object: QueryResult): ?string => {
      switch (object.__typename) {
        case 'Route':
          return `${object.__typename}:${object.name}`;
        default: return defaultDataIdFromObject(object);
      }
    };
    
    export function newCache(): InMemoryCache {
      return new InMemoryCache({ dataIdFromObject, cacheRedirects });
    }
    

    现在,当在客户机的几个地方使用查询时,我们希望只为没有通过网络缓存的routename获取数据,并通过缓存检索其余的数据。

    所以问题归结为: 当有一个缓存结果的查询时 routeNames: ["foo", "bar"] 后来又来了一个询问询问 routeNames: ["bar", "baz"] 我们希望得到相应的结果 "bar" 从缓存发送查询 routeNames: ["baz"] .

    我不确定阿波罗是否能做到这一点,以及如何做到这一点,因为与 cacheRedirect example 这里我们处理的是多个ID,而不是一个ID。


    现在,如果我们不能缓存每个数组项,接下来最好的方法是将id转换为公共缓存键,以便 ["foo", "bar"] ["bar", "foo"] 最终使用相同的缓存密钥,但是 ["foo", "baz"] 会用另一个。

    当然,理想的做法是只取 "baz" 在我们的场景中丢失的物品。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Mikael Lirbank    6 年前

    一个想法是在进行实际查询之前检查本地缓存,只需将缓存中已经存在的id(routename)从要查询的id(routename)列表中删除即可。

    要在不接触网络的情况下检查缓存,请使用 readQuery() readFragment() .

    文件如下:

    https://www.apollographql.com/docs/react/advanced/caching.html#readquery https://www.apollographql.com/docs/react/advanced/caching.html#readfragment

    更新:或者也可以设置 fetchPolicy cache-only 在查询选项中。

    https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-options-fetchPolicy

    更新2:集成检查以便为每个查询运行的一个很好的方法可能是自定义客户端中间件,它将在调用服务器之前对每个请求运行。

    https://www.apollographql.com/docs/react/advanced/network-layer.html#linkMiddleware