14

在 Relay/GraphQL 模式配置中,一对多关系(带分页)在教程示例中指定

type ShipConnection {
  edges: [ShipEdge]
  pageInfo: PageInfo!
}
type ShipEdge {
  cursor: String!
  node: Ship
}

但是,由 建立的一对一连接ShipEdge似乎是多余的。为什么我们不能将光标移动到IDShipConnection数组并将其存储为边?Ship

type ShipConnection {
  edges: [Ship]
  pageInfo: PageInfo!
  cursor: String!
}

edge在一对多关系中需要一个额外对象的设计决策是什么?

4

3 回答 3

14

(更新了更多解释)

在 GraphQL 中有 3 种方式来表示数据数组:

  1. 列表:当您有一个有限的关联对象列表时使用,您可以一次很好地获取所有对象。在 GraphQL SDL 中,这表示为[Ship].
  2. 节点:当您需要对列表进行分页时使用,通常是因为可能有数千个项目。请注意,这不是 Relay 规范的一部分,因此 Relay 客户端不支持(相反,您可以将项目包装在边缘中,如 #3 中所述),但其他一些客户端(例如 Apollo)更灵活,并且支持这种结构(但您需要提供更多样板文件)。在 GraphQL 中,这将表示为type ShipConnection { nodes: [Ship], pageInfo: PageInfo! }.
  3. 边缘:除了分页之外,您还需要为连接中的每个边缘提供额外信息时使用(阅读下文了解更多详细信息)。在 GraphQL 中,您可以将其编写为type ShipConnection { edges: [ShipEdge], pageInfo: PageInfo! }.

请注意,您的 GraphQL 服务器可能支持特定关联的所有三个选项,然后客户端选择他们想要的字段。以下是它们的外观:

type Query {
  ships: [Ship]       // #1
  shipsConnection: [ShipConnection]
}

type ShipConnection {
  nodes: [Ship]       // #2
  edges: [ShipEdge]   // #3
  pageInfo: PageInfo!
}

type PageInfo {
  endCursor           // page-based pagination
  hasNextPage
}

type ShipEdge {
  cursor: String!     // edge-based pagination
  node: Ship
  // ... edge attributes
}

type Ship {
  // ... ship attributes
}

仅当您知道项目的数量不会增加时才应该使用列表(#1)(例如,如果您有一个Post,您可能希望tags作为一个列表返回,但您不应该这样做comments)。要在 #2 和 #3 之间做出决定,仅在普通节点上使用边有两个原因:

  • 它是边缘特定属性的地方。例如,如果您有一个User属于许多Groups 的 a,那么在关系数据库中您将有一个带有user_idand的 UserGroup 表group_id。该表可以具有其他属性role,例如joined_at等。GroupUserEdge然后您可以访问这些属性的位置。

  • 为光标留一个位置。Relay,除了基于页面的分页(使用pageInfo)支持基于边缘的分页。为什么 Relay 每个边都需要一个光标?由于 Relay 智能地合并了来自整个应用程序的数据需求,它可能已经与您请求的相同参数建立了连接,但其中没有足够的记录。为了获取丢失的数据,它可以在某个边缘的光标之后请求连接中的数据。

    我知道这可能会让人感到困惑,因为数据库也有游标,而且每个查询只有一个游标。中继连接实际上并不是一个查询,而是一组标识查询的参数。连接边缘的光标是一组参数,用于标识连接中的位置。这是比纯查询游标更高的抽象级别(请记住,即使在可能不是数据库查询或被第 3 方系统隐藏的连接上,边缘也需要能够识别位置)。由于需要灵活性,一个连接的光标是不够的。

于 2015-12-10T03:44:21.063 回答
9

edges字段为您提供了放置每个边缘数据的位置。例如,您可能希望在其中放置一个creatorpriority字段,分别描述谁添加了边缘以及关系的重要性。

如果您不需要这种灵活性(或通过连接获得的其他功能,例如分页),您可以使用简单GraphQLList类型。有关连接和列表之间区别的更多信息,请参阅此答案。

于 2015-10-25T16:29:25.200 回答
5

我们写了一篇关于简单 GraphQL 模式与 Relay 特定模式之间差异的博客文章:

https://www.prisma.io/blog/connections-edges-nodes-in-relay-758d358aa4c7

于 2016-06-02T12:46:36.857 回答