PlayerとTeam という2 つのエンティティがあり、プレイヤーが複数のチームに所属できるとします。私のデータ モデルには、各エンティティのテーブルと、関係を維持するための結合テーブルがあります。休止状態これを扱うのは良いのですが、この関係をどのように公開すればよいのでしょうかRESTfulAPI?
いくつかの方法が考えられます。まず、各エンティティに他のエンティティのリストを含めることで、プレーヤーオブジェクトには所属するチームのリストが含まれ、各チームオブジェクトには所属するプレーヤーのリストが含まれます。つまり、プレーヤーをチームに追加するには、役職プレイヤーの表現をエンドポイントに渡すもので、POST/player
や、リクエストのペイロードとして適切なオブジェクトを持つ POSTなどです/team
。これは私にとって最も「RESTful」なように思えますが、少し奇妙に感じます。
/api/team/0:
{
name: 'Boston Celtics',
logo: '/img/Celtics.png',
players: [
'/api/player/20',
'/api/player/5',
'/api/player/34'
]
}
/api/player/20:
{
pk: 20,
name: 'Ray Allen',
birth: '1975-07-20T02:00:00Z',
team: '/api/team/0'
}
これを行うために私が思いつくもう 1 つの方法は、関係をそれ自体のリソースとして公開することです。つまり、特定のチームのすべてのプレーヤーのリストを表示するには、GET などを実行して、PlayerTeam エンティティのリストを取得します。プレーヤーをチームに追加するには、適切に構築された PlayerTeam エンティティをペイロードとして/playerteam/team/{id}
POST します。/playerteam
/api/team/0:
{
name: 'Boston Celtics',
logo: '/img/Celtics.png'
}
/api/player/20:
{
pk: 20,
name: 'Ray Allen',
birth: '1975-07-20T02:00:00Z',
team: '/api/team/0'
}
/api/player/team/0/:
[
'/api/player/20',
'/api/player/5',
'/api/player/34'
]
これに対するベストプラクティスは何でしょうか?
ベストアンサー1
別のリソース セットを作成します/memberships/
。
- REST は、何はともあれ進化可能なシステムを作ることです。現時点では、特定のプレイヤーが特定のチームに所属しているということだけを気にしているかもしれませんが、将来のある時点で、その関係にさらに多くのデータ (そのチームに所属している期間、そのチームに紹介した人物、そのチームに所属していたときのコーチは誰かなど) を注釈付けしたくなるでしょう。
- REST は効率化のためにキャッシュに依存しており、キャッシュの原子性と無効化について考慮する必要があります。新しいエンティティを
/teams/3/players/
そのリストに POST すると、そのエンティティは無効化されますが、代替 URL が/players/5/teams/
キャッシュされたままになるのは望ましくありません。確かに、異なるキャッシュには、異なる年齢の各リストのコピーがあり、それについては私たちにできることはあまりありませんが、クライアントのローカル キャッシュで無効化する必要のあるエンティティの数を1 つだけに制限することで、更新を POST するユーザーの混乱を最小限に抑えることができます/memberships/98745
(Helland の「代替インデックス」に関する説明を参照)。分散トランザクションを超えた生活より詳細な議論については、こちらをご覧ください。 - 上記の 2 つのポイントは、
/players/5/teams
または/teams/3/players
(両方ではありません) を選択するだけで実装できます。前者を想定してみましょう。ただし、ある時点で、現在の/players/5/teams/
メンバーシップのリストを予約し、過去のメンバーシップをどこかで参照できるようにする必要があります。リソースへのハイパーリンクのリストを作成し、個々のメンバーシップ リソースのすべてのブックマークを壊すことなく、必要なときに追加できます。これは一般的な概念です。特定のケースにもっと当てはまる他の同様の未来を想像できると思います。/players/5/memberships/
/memberships/{id}/
/players/5/past_memberships/