如何告诉 apollo-client 不要对特定字段应用规范化?

How to tell apollo-client to not apply normalization on specific fields?

我的 GraphQL 架构包括具有大量数据的对象,这些数据是该对象独有的,不会在其他对象中找到。

示例:

type Position {
  time: Integer
  latitude: Float
  longitude: Float
}

type ObjectInSpaceAndTime {
  name: String
  positions(start: Int, end: Int): [Position]
}

我对 GraphQL Client 规范化的理解是,响应图将被展平,Position 的每个实例在缓存中提取,为其创建一个唯一的键(从位置的路径,所以像someobject.positions.42)。这是非常 CPU 和内存密集型的,有数千个值。

缓存将如下所示:

{
  __ObjectInSpaceAndTime.someid: {name: 'xxx'},
  __ObjectInSpaceAndTime.someid.positions.0: {time: 1221121, latitude: 0, longitude: 0},
  __ObjectInSpaceAndTime.someid.positions.1: {time: 1221122, latitude: 0, longitude: 0},
  // ...
}

相反,我想告诉 Apollo Client 不要尝试对其进行规范化,而只是存储 ObjectInSpaceAndTime 的整个实例及其字段,也许还有传递给字段的参数,以便具有不同的查询属性产生缓存未命中。 这将显着减少 apollo 在处理回复时必须在内存中做的工作。数据数组将从响应中反序列化一次,无需 apollo-client 迭代即可使用。

{
  __ObjectInSpaceAndTime.someid: {name: 'xxx', 
       positions: [ {time: 1221121, latitude: 0, longitude: 0}, 
                    {time: 1221122, latitude:0, longitude: 0}, 
                    /* ... */ ], 
  // ...
}

Apollo Client 可以吗?我找不到办法做到这一点。

也欢迎就此建模的更好方法提出建议 "graph"。

到目前为止我找到的最佳解决方案是切换到另一个缓存,即apollo-cache-hermes。 Hermes 只会存储他们所谓的 "Entities",即返回一个带有 'id' 的对象(我正在简化,但这是默认行为)。

我写了一个简单的基准测试工具,获取一个关联了 12k "points" 数组的对象。该点的属性之一是带有纬度和经度键的 GPS 坐标。

使用默认的 apollo-inmemory 缓存,我得到:

1st query (not cached)
Network time: 2358ms
Received data navDataCount=12860 Timer=3013ms  Memory=82.41MB CacheEntries=25722
2nd query (cached)
Received data navDataCount=12860 Timer=19ms  Memory=86.26MB  CacheEntries=25722

缓存中的处理时间:655 毫秒

与 apollo-hermes:

1st query (not cached)
Network time: 2891ms
Received data navDataCount=12860 Timer=3079ms  Memory=23.36MB  CacheEntries=3
2nd query (cached)
Received data navDataCount=12860 Timer=51ms  Memory=22.37MB  CacheEntries=3

缓存中的处理时间:188ms

(我运行多次测试,处理时间相差不大)。

虽然我对 apollo-inmemory 对第二个查询的响应速度如此之快感到惊讶,但对我来说这似乎是一个很好的解决方案。 655 毫秒是处理如此大量对象的不错时间,内存中的 apollo 仍然是一个非常可靠的选择。