(より多くの説明で更新されました)
GraphQL でデータの配列を表す方法は 3 つあります。
- リスト: 一度にすべて取得しても問題ない関連オブジェクトのリストが有限である場合に使用します。GraphQL SDL では、これは として表され
[Ship]
ます。
- ノード: 通常、数千のアイテムが存在する可能性があるため、リストをページ分割する必要がある場合に使用します。これは Relay 仕様の一部ではないため、Relay クライアントではサポートされていないことに注意してください (代わりに、#3 で説明されているようにアイテムをエッジでラップします)。ただし、Apollo などの他のクライアントはより柔軟で、この構成をサポートします (ただし、ボイラープレートをさらに提供する必要があります)。GraphQL では、これは として表され
type ShipConnection { nodes: [Ship], pageInfo: PageInfo! }
ます。
- エッジ: ページネーションに加えて、接続の各エッジに追加情報を提供する必要がある場合に使用します (詳細については以下をお読みください)。GraphQL では、次のように記述します
type ShipConnection { edges: [ShipEdge], pageInfo: PageInfo! }
。
GraphQL サーバーは、特定の関連付けに対して 3 つのオプションすべてをサポートしている可能性があり、クライアントは必要なフィールドを選択することに注意してください。これらをすべて組み合わせると、次のようになります。
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 のどちらかを決定するには、単純なノードだけでエッジを使用する理由が 2 つあります。
これは、エッジ固有の属性の場所です。たとえば、User
多くの に属するがある場合Group
、リレーショナル データベースには および を持つ UserGroup テーブルがuser_id
ありgroup_id
ます。このテーブルにはrole
、joined_at
などの追加の属性GroupUserEdge
を含めることができます。これらの属性にアクセスできる場所は になります。
カーソルを置く場所を確保します。ページベースのページネーション ( を使用) に加えて、RelaypageInfo
はエッジベースのページネーションをサポートします。Relayがエッジごとにカーソルを必要とするのはなぜですか? Relay はアプリ全体からのデータ要件をインテリジェントにマージするため、リクエストしている同じパラメーターとの接続が既に存在する可能性がありますが、十分なレコードがありません。欠落しているデータを取得するために、エッジのカーソルの後の接続でデータを要求できます。
データベースにもカーソルがあり、クエリごとにカーソルが 1 つしかないことを考えると、混乱する可能性があることは理解しています。リレー接続は実際にはクエリではなく、クエリを識別する一連のパラメーターです。接続のエッジのカーソルは、接続内の位置を識別するパラメーターのセットです。これは、純粋なクエリ カーソルよりも高い抽象化レベルです (エッジは、DB クエリではない接続やサード パーティ システムによって隠されている可能性がある接続でも位置を識別できる必要があることに注意してください)。この必要な柔軟性のため、1 つの接続に 1 つのカーソルでは不十分です。