繁体   English   中英

Graphql 具有 id 属性的类型,相同的 id 可以有不同的值

[英]Graphql type with id property that can have different values for same id

我想知道具有 id 属性的 object 类型在给定相同 id 的情况下是否必须具有相同的内容。 目前同一个id可以有不同的内容。

以下查询:

const query = gql`
  query products(
    $priceSelector: PriceSelectorInput!
  ) {
    productProjectionSearch(
      priceSelector: $priceSelector
    ) {
      total
      results {
        masterVariant {
          # If you do the following it will work
          # anythingButId: id
          id
          scopedPrice {
            country
          }
        }
      }
    }
  }
`;

如果PriceSelectorInput{currency: "USD", country: "US"}那么结果是:

{
  "productProjectionSearch": {
    "total": 2702,
    "results": [
      {
        "name": "Sweater Pinko white",
        "masterVariant": {
          "id": 1,
          "scopedPrice": {
            "country": "US",
            "__typename": "ScopedPrice"
          },
          "__typename": "ProductSearchVariant"
        },
        "__typename": "ProductProjection"
      }
    ],
    "__typename": "ProductProjectionSearchResult"
  }
}

如果PriceSelectorInput{currency: "EUR", country: "DE"}那么结果是:

{
  "productProjectionSearch": {
    "total": 2702,
    "results": [
      {
        "name": "Sweater Pinko white",
        "masterVariant": {
          "id": 1,
          "scopedPrice": {
            "country": "DE",
            "__typename": "ScopedPrice"
          },
          "__typename": "ProductSearchVariant"
        },
        "__typename": "ProductProjection"
      }
    ],
    "__typename": "ProductProjectionSearchResult"
  }
}

我的问题是,ProductSearchVariant 类型的 masterVariant 在这两种情况下的 id 均为 1,但 scopedPrice 的值不同。 本回购协议所示,这会破坏 apollo 缓存 defaultDataIdFromObject function。 我的问题是; 这是 apollo 中的错误还是违反了 ProductSearchVariant 类型定义中的 graphql 标准?

TLDR

不,它不会违反规范。 该规范在缓存方面绝对没有任何强制性。

可能感兴趣的人的文学

从概述部分的末尾开始

由于这些原则,[...一个] 可以在不阅读大量文档并且很少或根本没有接受正式培训的情况下迅速变得富有成效。 为了实现这种体验,必须有那些构建这些服务器和工具的人。

以下正式规范供那些建设者参考。 它描述了语言及其语法、类型系统和用于查询它的内省系统,以及执行和验证引擎以及为它们提供动力的算法。 本规范的目标是为尚未构建的 GraphQL 工具、客户端库和服务器实现的生态系统提供基础和框架——跨越组织和平台。 我们期待与社区合作以实现这一目标。

正如我们刚刚看到的规范中没有提到缓存或实现细节,这些都留给了社区。 该论文的 rest 继续详细说明应如何处理类型系统、语言、请求和响应。

另请注意,该文档没有提及正在使用的底层协议(尽管通常是 HTTP)。 您可以通过 USB 设备或红外线有效地运行 GraphQL 通信。

我们在技术会议上举办了一次有趣的演讲,您可能会觉得很有趣。 这是一个链接:

GraphQL Anywhere - 我们的 GraphQL 网格和模式拼接之旅 • Uri Goldshtein • GOTO 2021

如果我们自己“Ctrl+F”来查找“缓存”或“ID”之类的东西,我们可以找到以下部分,我认为这有助于在这里得出结论:

ID

ID 标量类型表示唯一标识符,通常用于重新获取 object 或用作缓存的键。 ID 类型以与 String 相同的方式序列化; 但是,它并不是为了人类可读的。 虽然它通常是数字,但它应该始终序列化为字符串。

结果强制

GraphQL 与 ID 格式无关,并序列化为字符串以确保 ID 可以表示的多种格式的一致性,从小的自动递增数字到大的 128 位随机数,再到 base64 编码值,或 GUID 等格式的字符串值。

GraphQL 服务器应该根据他们期望的 ID 格式进行适当的强制转换。 当强制不可能时,他们必须提出一个字段错误。

输入强制

当预期作为输入类型时,任何字符串(例如“4”)或 integer(例如 4)输入值都应根据给定 GraphQL 服务器期望的 ID 格式强制转换为 ID。 任何其他输入值,包括浮点输入值(例如 4.0),都必须引发查询错误,指示类型不正确。

它提到该字段通常用作缓存键(这是 GraphQL 实现的 Apollo 集合的默认缓存键),但它没有告诉我们任何关于“返回数据的一致性”的信息。

这是 GraphQL 的完整规范文档的链接

警告! 自以为是——我对身份证的看法

当然我要说的一切都与GraphQL规范无关

有时一个ID不足以作为一条信息来决定是否缓存某些东西。 让我们考虑一下用户搜索:

如果我有一个FavouriteSearch实体,它在我的数据库中有一个 ID 和一个名为textSearch的字段。 我通常想公开一个属性results: [Result!]! 在我的 GraphQL 规范中引用了这个特定文本搜索产生的所有结果。

这些结果很可能与我进行搜索时或五分钟后我重新访问我最喜欢的搜索时不同。 (考虑在 TikTok 等用户可能会大量上传内容的平台上进行文本搜索)。

因此,基于实体FavouriteSearch的定义,缓存行为相当出乎意料是有道理的。

如果我们从不同的角度考虑这个问题,我们可能需要一个SearchResults实体,它可以有一个 ID 和一个时间戳,并且有一个连接表,我们在其中引用所有与初始文本搜索相关的帖子,在这种情况下它为我们的 GraphQL 模式返回一致的属性results内容是有意义的。

事情是,这取决于我们如何定义我们的实体,它最终与 GraphQL 规范无关

您的问题的解决方案

您可以指定 Apollo 如何生成密钥以供以后用作缓存中的密钥,正如 @Matt 已经在评论中指出的那样。 您可能想要利用它并覆盖那些__type等于您的masterVariant属性类型的实体的行为,并为所有这些(或类似的)返回 NO_KEY 以避免从您的 ApolloClient 在这些特定字段上进行缓存。

我希望这可以帮到你!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM