web-dev-qa-db-ja.com

RESTfulサービスで順序付きリストリソースをどのように設計すればよいですか?

この同じ問題に何度も遭遇しましたが、本当に最適だと感じた解決策が見つかりませんでした。

アプリで、順序付けられたリストがあり、ユーザーがドラッグアンドドロップなどでその順序を変更できるようにします。変更を永続化する必要があります。それをどのようにモデル化しますか?

順序付きリストリソースのサービスを設計するにはどうすればよいですか?

特に、残りのリソースのlistおよびitemモデルをどのように設計すればよいですか?私が目にした最も一般的なデザインは、itemまたはorderプロパティを持つpositionエンティティです。私が聞いたもう1つのアプローチは、項目の二重リンクリストです。

データベースへの書き込みが多すぎず、一般的にクライアントに対して更新と読み取りが高速なアプローチは何ですか?エンドポイントはどのように公開する必要がありますか?

11
Rico Kahler

順序付きリストを表すことは、リレーショナルデータベースの難しい問題の1つです。リストメンバーシップ関係に位置プロパティを追加するのが最も一般的な方法です。これは、SQLクエリにORDER BY positionを追加することで順序付きリストを簡単に取得でき、アイテムを途中に簡単に挿入できるためです。位置が整数ではなく浮動小数点数であると想定して、前後のリストメンバーの値を平均することによるリスト。

誤ってリンクを不整合にして、代わりに循環グラフまたはツリーになってしまう可能性があるため、二重リンクリストの使用は避けてください。

ただし、RESTful APIはリレーショナルデータベースの制限の影響を受けません。位置プロパティのようなハックを使用するのではなく、自然に感じることを実行できます。

リストに数百までの要素しかない場合は、リクエスト全体でリスト全体を転送します。リストのメンバーがIDである[1, 2, 3, 4]を並べ替えたいとすると、

POST /url/of/the/list
Content-type: application/json
...

[1, 2, 4, 3]

バックエンドはこれを、使用しているデータベーステクノロジーに変換しますが、APIユーザーはこれらの詳細を考慮する必要はありません。

リストが大きく、通常アイテムが個別にリクエストされる場合は、URLのインデックスを許可できます。

GET /page/7

HATEOASを使用している場合、通常はリソースがそのように消費されるのであれば、ナビゲーションを単純にするために応答に前/次のリンクを含めることができます。ただし、これはデータベースにこの二重リンクリストが含まれていることを意味する必要はありません。

リストが非常に大きい場合は、ArrayListinsert/Pushなどのappendに似た操作を公開することをお勧めします。私は次のような電話を想像できました

POST /url/of/the/list?at=1357;mode=insert
...

description of the item to insert

並べ替えが一般的なユースケースであり、並べ替えをすぐにコミットする必要がある場合は、APIで適切なエンドポイントを提供できます。

POST /url/of/the/list/reorder-item?from=783;to=1357

並べ替えられたリストを明示的にコミットする必要がある場合は、新しい注文をJSONドキュメントとして転送する方が簡単です(上記を参照)。

現在、APIを、使用しているデータベーステクノロジーとは完全に分離されていると見なすことは、必ずしも正しくありません。ただし、外部APIを実装の詳細からできるだけ自由にしておくことをお勧めします。整数の順序列を更新するためだけに並べ替えが約30行に達する場合、それは大した問題ではありません。できるだけ簡単なことを行い、常にリスト全体を更新してください。規模に応じてデータベースの使用をより高度にする必要がある場合は、一貫性を維持しやすいバックエンドでこの高度な機能をキャプチャすることをお勧めします。

14
amon

さまざまなアプローチの実行可能性は、使用されている基礎となるデータベースに大きく依存すると思います。

このアプローチは、順序付けでアイテムを移動することを提案しました:

POST/url/of/the/list/reorder-item?from = 783; to = 1357

SERIALIZABLEトランザクション性がない限り、競合状態になる可能性があります。ほとんどのDBのデフォルトレベルのREAD_COMMITTEDでは、競合状態は解消されません!

私は実際に、ほとんどの場合-リストが比較的小さい限り-全リスト置換アプローチは競合状態の問題が少なく、データを破壊できないと思います。クライアントがリクエストを行ってからアイテムのセットが変更されている場合は、409(競合)を返すことができます。

それは最後の書き込みの勝利に苦しんでいますが、それは文字通りすべてのAPIに当てはまります。実装しているAPIに関係なく、ページの表示中に別のクライアントが更新した可能性があります。

2
Charles Capps