【问题标题】:How to tell apollo-client to not apply normalization on specific fields?如何告诉 apollo-client 不对特定字段应用规范化?
【发布时间】:2019-06-15 20:39:59
【问题描述】:

我的 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 客户端不要尝试对此进行规范化,而只存储 ObjectInSpaceAndTime 的整个实例及其字段,也许还有传递给字段的参数,以便具有不同属性的查询产生缓存-错过。 这将显着减少 apollo 在处理回复时必须在内存中做的工作。数据数组将从响应中反序列化一次,并且无需 apollo-client 对其进行迭代即可使用。

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

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

也欢迎提出更好的方法来模拟这个“图表”。

【问题讨论】:

  • apollo-cache-hermes 看起来是解决我问题的好方法。 Motivation 文档在解释我遇到的问题方面做得很好。
  • "这非常占用 CPU 和内存,有数千个值。" - 为什么不使用分页策略,一次在内存中存储更少的值?
  • 在我的用例中,我需要所有数据点来绘制变量图或在地图上绘制位置历史记录。服务器可以进行预处理以减少值的数量,但仍然需要内存中的大量行来进行绘图。
  • 我们有同样的问题,但由于各种原因,Hermes 目前不是一个选择,即使我已经测试过它并且它的性能要好得多。

标签: graphql apollo apollo-client


【解决方案1】:

目前我发现的最佳解决方案是切换到另一个缓存,即apollo-cache-hermes。 Hermes 只会存储他们所谓的“实体”,即返回一个“id”的对象(我正在简化,但这是默认行为)。

我编写了一个简单的基准测试工具,获取一个包含 12k 个“点”数组的对象。该点的属性之一是带有纬度和经度键的 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

在缓存中的处理时间:655ms

与阿波罗爱马仕:

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 对第二个查询的响应速度感到惊讶。 655ms 不是处理如此大量对象的好时机,apollo-inmemory 仍然是一个非常可靠的选择。

【讨论】:

  • 哇,谢谢,这怎么没有更多的赞成票!我有大量像这样的嵌套 JSON 对象,Apollo 缓存不断对它们进行规范化,然后在它们没有 ID 时返回错误的对象......不过我会尝试 Hermes
猜你喜欢
  • 2020-10-24
  • 2021-09-30
  • 2017-05-28
  • 1970-01-01
  • 2020-05-26
  • 2016-08-15
  • 2018-03-03
  • 2021-02-14
  • 1970-01-01
相关资源
最近更新 更多