RESTを使用して複数のレコードを削除する


97

複数のアイテムを削除するRESTフルな方法は何ですか?

私のユースケースは、複数のアイテムを一度に削除できる必要があるバックボーンコレクションを持っている場合です。オプションは次のようです:

  1. すべてのレコードに対してDELETEリクエストを送信します(数十のアイテムが存在する可能性がある場合、これは悪い考えのようです)。
  2. 削除するIDがURLでつながっているDELETEを送信します(つまり、「/ records / 1; 2; 3」)。
  3. REST以外の方法では、削除対象としてマークされたIDを含むカスタムJSONオブジェクトを送信します。

すべてのオプションは理想的ではありません。

これはREST規約の灰色の領域のようです。


3
一連

回答:


92
  1. これは実行可能なRESTfulな選択ですが、説明した制限があることは明らかです。
  2. これを行わないでください。仲介者によって「DELETE((single)resource at)」を意味すると解釈されます/records/1;2;3—したがって、これに対する2xx応答は/records/1;2;3、それらのキャッシュをパージする可能性があります。ないパージ/records/1/records/2または/records/3; 410の応答/records/1;2;3、またはあなたの観点からは意味のない他のものをプロキシします。
  3. この選択が最善であり RESTfulに実行できます。APIを作成していて、リソースへの一括変更を許可したい場合は、RESTを使用してそれを行うことができますが、正確な方法は多くの人にはすぐにはわかりません。一つの方法は、することがある「変更要求」リソースを作成(例のような身体を掲載することによりrecords=[1,2,3]までを/delete-requests)し、作成したリソース(で指定されたポーリングLocation、あなたの要求が受け入れられたかどうかを調べるには、応答のヘッダを)拒否され、進行中ですまたは完了しました。これは、長時間実行される操作に役立ちます。別の方法は、リストリソースにリクエスト送信するPATCHことです/records、その本文には、リソースとそれらのリソースに対して実行するアクションのリストが含まれます(サポートしたい形式で)。これは、要求の応答コードが操作の結果を示すことができる迅速な操作に役立ちます。

RESTの制約を守りながらすべてを達成できます。通常の答えは、「問題」をリソースにしてURLを与えることです。
したがって、ここでの削除、リストへの複数のアイテムのPOST、またはリソースのスウォースへの同じ編集などのバッチ操作は、すべて「バッチ操作」リストを作成し、それに新しい操作をPOSTすることで処理できます。

忘れないでください。RESTが問題を解決する唯一の方法ではありません。「RESTは」ただの建築様式であり、あなたはしていない持って、それに付着する(しかし、そうでない場合は、インターネットの特定の利点を失います)。このHTTP APIアーキテクチャのリストを調べて、自分に合ったものを選択することをお勧めします。別のアーキテクチャを選択した場合に何を失うかを自分自身に認識させ、ユースケースに基づいて情報に基づいた決定を下してください。

REST Webサービスでバッチ操作を処理するためのパターンに関するこの質問に対するいくつかの悪い答えはありますか?賛成票が多すぎますが、読むべきです。


2
心配する必要があるのはサーバーではなく、仲介者、CDN、キャッシュプロキシなどです。インターネットは階層型システムです。それがとてもうまくいく理由です。Royは、システムの成功に必要なシステムの側面を判断し、RESTと命名しました。DELETE要求を発行すると、要求先とサーバーの間にあるものはすべて、指定されたURLにある単一のリソースが削除されていると見なします。クエリ文字列は、これらのデバイスへのURLの不透明な部分であるため、APIをどのように指定するかは関係ありません。これらはこの知識に関係がないため、異なる動作をすることはできません。
Nicholas Shanks、2014

3
/ records / 1; 2; 3は、UR​​Iの長さに制限があるため、削除するリソースが多い場合は機能しません
dukethrash

3
DELETEと、削除するリソースを定義する本文を検討する場合、一部の仲介者が本文を転送しない可能性があることに注意してください。また、一部のHTTPクライアントは、DELETEに本文を追加できません。stackoverflow.com/questions/299628/…を
Luke Puplett 2016

3
@LukePuplettリクエストにリクエスト本文を渡すことDELETEは禁止されていると私は単に述べます。しないでください。もしそうなら私はあなたの子供たちを食べます。Nom nom nom。
ニコラスシャンクス2016

3
#3の引数の問題は、それが#2に対する反対の引数と同じペナルティを運ぶことです。削除するリソースの作成は、アップストリームプロキシが処理する方法を知っているものではありません-アプローチ#2に対して発生する同じカウンター引数。
LB2

16

GET /records?filteringCriteria条件に一致するすべてのレコードの配列を返す場合、そのDELETE /records?filteringCriteriaようなレコードをすべて削除できます。

この場合、あなたの質問に対する答えはになりますDELETE /records?id=1&id=2&id=3


1
私もこの結論に達しました。動詞をあなたがやりたいことへとひっくり返すだけです。GETで何がDELETEにならないのかわかりません。
ルークプレット

9
GET /records?id=1&id=2&id=3「ID 1、2、3の3つのレコードを取得する」という意味ではなく、「URLパス/ records?id = 1&id = 2&id = 3の単一のリソースを取得する」ことを意味します。中国語の "42"を含む文書、または存在しない可能性があります。
Nicholas Shanks、2015

次のことを考慮してください。2つの順次要求/records?id=1/records?id=2が送信され、それらの応答は何らかの仲介者(ブラウザやISPなど)によってキャッシュされます。インターネットがあなたのアプリケーションがこれによって何を意味するかを知っていれば、/records?id=1&id=2元のサーバーに問い合わせることなく、すでにある2つの結果を(どういうわけか)マージするだけで、リクエストがキャッシュによって返される可能性があります。しかし、これは不可能です。/records?id=1&id=2無効(リクエストごとに許可されるIDは1つのみ)または完全に異なるもの(カブ)が返される場合があります。
Nicholas Shanks、2015

これは、基本的なリソースキャッシュの問題です。私のDBAが状態を直接変更した場合、キャッシュは同期しなくなります。仲介者から返された410の例を示しますが、410は完全に削除するためのものです。DELETEを実行すると、キャッシュはそのURLのスロットをクリアする可能性がありますが、DBAかどうかがわからないため、410または404は送信されません。リソースをすぐに元に戻しただけではありません。
ルークプレット16

4
@NicholasShanks私は本当に同意しません。結果がキャッシュされる場合、それはサーバーの障害です。そして、もしあなたがAPIの設計について話しているなら、うまくいけばサーバーのコードを書いているのはあなたです。値の配列を表すために、id[]=1&id[]=2またはid=1&id=2クエリ文字列で使用するかどうかにかかわらず、そのクエリ文字列はまさにそれを表します。そして、クエリ文字列がフィルターを表すことは非常に一般的で良い習慣だと思います。また、削除と更新を許可する場合は、GETリクエストをキャッシュしないでください。その場合、クライアントは古い状態を保持します。
ジョセフNields 2017年

8

Mozilla Storage Service SyncStorage API v1.5は、RESTを使用して複数のレコードを削除する良い方法だと思います。

コレクション全体を削除します。

DELETE https://<endpoint-url>/storage/<collection>

1つの要求でコレクションから複数のBSOを削除します。

DELETE https://<endpoint-url>/storage/<collection>?ids=<ids>

ids:提供されたコンマ区切りのリストにあるIDを持つコレクションからBSOを削除します。最大100個のIDを指定できます。

指定された場所にあるBSOを削除します。

DELETE https://<endpoint-url>/storage/<collection>/<id>

http://moz-services-docs.readthedocs.io/en/latest/storage/apis-1.5.html#api-instructions


これ良い解決策のようです。モジラがそれが正しいと思うなら、それは正しいに違いないと思いますか?唯一の問題は、エラー処理です。それらが?ids = 1,2,3を渡し、id 3が存在しない場合、1と2を削除してから200で応答します。リクエスターは3が必要で、そこにないため、問題ありませんか?または、1は削除できるが2は許可されていない場合...何も削除せずにエラーで応答するか、またはできるものを削除して他のユーザーを残しますか?
tempcke

いずれにしても終了状態は同じであるため、通常は正常な応答を返します。これにより、エラー状態を処理する必要がなくなるため、クライアントのロジックも簡素化されます。認可の場合は、リクエスト全体が失敗しますが、実際にはユースケースによって異なります。
Nathan Phetteplace

3

これはREST規約の灰色の領域のようです。

はい、これまでのところ、バッチ操作(バッチ削除など)について言及しているREST API設計ガイドの1つであるgoogle api設計ガイドに出くわしました。

このガイドで、コロンを使用してリソースを介して関連付けることができる「カスタム」メソッドの作成について言及しています。たとえばhttps://service.name/v1/some/resource/name:customVerb、ユースケースとしてバッチ操作についても明示的に言及しています。

カスタムメソッドは、リソース、コレクション、またはサービスに関連付けることができます。任意の要求を受け取り、任意の応答を返す可能性があり、ストリーミング要求と応答もサポートしています。[...]カスタムメソッドは最も柔軟なセマンティクスを持っているため、HTTP POST動詞を使用する必要があります[...]パフォーマンスが重要なメソッドの場合、カスタムバッチメソッドを提供してリクエストごとのオーバーヘッドを減らすと役立つ場合があります

したがって、GoogleのAPIガイドに従って、次のことを実行できます。

POST /api/path/to/your/collection:batchDelete

...コレクションリソースのアイテムの束を削除します。


項目のリストがJSON形式の配列を介して通信される実行可能なソリューションですか?
Daniele

はい確かに。idがjson配列を介して送信されるペイロードをPOSTできます。
B12Toaster

Google APIガイドIf the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all,がカスタムメソッドの章で言ったことは興味深いです。ただし、 GET accounts.locations.batchGetAPIはボディ付きのGETメソッドです。それは奇妙です。developers.google.com/my-business/reference/rest/v4/...
鄭元傑

@鄭元傑は同意します。一見すると少し奇妙に見えますが、よく見ると実際にはPOSThttpメソッドが使用されており、カスタムメソッドのみが指定されていbatchGetます。私はグーグルがそれを(a)すべてのカスタムメソッドが必要であるというルールを守るPOST(私の答えを参照)、そして(b)人々がボディに「フィルター」を簡単に置くことができるようにして、あなたがする必要がないようにするのだと思いますクエリ文字列と同様に、フィルターをエスケープまたはエンコードします。もちろん、欠点は、これが実際にはもうキャッシュできないことです...
B12Toaster

https://service.name/v1/some/resource/name:customVerb定義上、RESTfulではありません。
デーモン

2

たとえばPUT ~/people/123/shoes、本体がコレクション全体の表現である場合など、コレクションの大規模な置き換えを許可しました。

これは、クライアントがアイテムを確認し、一部をプルーニングして他の一部を追加し、サーバーを更新する必要があるアイテムの小さな子コレクションに対して機能します。空のコレクションをPUTして、すべてを削除できます。

これはGET ~/people/123/shoes/9、PUTが削除してもキャッシュに残っていることを意味しますが、これは単なるキャッシュの問題であり、他の誰かが靴を削除した場合に問題になります。

データ/システムAPIは、有効期限ではなく常にETagを使用するため、リクエストごとにサーバーがヒットし、データを変更するには正しいバージョン/同時実行ヘッダーが必要です。読み取り専用で、ビュー/レポートに調整されたAPIの場合、有効期限を使用して、オリジンへのヒットを減らします。たとえば、リーダーボードは10分間有効です。

のようなはるかに大きなコレクションの場合~/people、私は複数の削除を必要としない傾向があり、ユースケースは自然に発生しない傾向があるため、単一のDELETEは正常に機能します。

将来的には、REST APIの構築や、監査などの同じ問題や要件に当てはまった経験から、GET動詞とPOST動詞のみを使用し、イベントに関する設計(例:POST a change of addressイベント)を使用する傾向がありますが、独自の一連の問題が付属します:)

また、厳密な「Fielding zealot」REST API設計を望まず、生産性とキャッシュ階層化の理由。


最後の文を読むまでは、この答えが気に入りました:)厳密なRESTを適用することで最終的に悪影響が生じるユースケースを見たことがありません。確かに、両端でより多くのコードを記述できるようになりますが、最終的には、より安全で、クリーンで、結合度の低いシステムになります。
ニコラスシャンクス2017年

はは。実際にパターンになっています!フロントエンドのバックエンドは、ThoughtWorksテクノロジーレーダーで呼び出されます。また、JavaScriptなどでは面倒なアプリケーションロジックをさらに記述でき、クライアントなしで更新できるため、たとえばiOSアプリの場合は更新することができます。
ルークプレット2017年

Googleからの最初の4つのヒットをざっと読むと、このBFF手法はクライアントがあなたの管理下にある場合にのみ機能するようです。クライアント開発者は必要なAPIを開発し、実際のバックエンドであるマイクロサービスAPIに呼び出しをマッピングします。この図では:samnewman.io/patterns/architectural/bff/#bff「境界線」をBFFボックスのに配置します。各ボックスは単にクライアントの一部です。マイクロサービスを収容するデータセンターの外に住むことさえできます。また、RESTが両方のインターフェイス(クライアント/ BFFおよびBFF /マイクロサービス)に適用されないこともわかりません。
ニコラスシャンクス2017年

1
ええ、それは良い点です。これは通常、たとえば、マイクロサービスを構築しているチームと、角度のあるアプリを作成しているチームがあり、その開発チームが、多くの小さな純粋なサービスに対して作業する必要がない、よりフロントエンドのタイプである場合に適しています。マイクロサービスを抽象化するために同じパターンを使用できず、顧客にとってより使いやすいファサードに集約できないので、ファサードに影響を与えずにマイクロサービスを変更できる理由はないと思います。
ルークプレット

APIエンドポイントは、ドメインとビジネスのニーズをモデル化する必要があります。それらの問題を解決し、厳格で多くの時代の柔軟性に欠ける仕様に準拠するための過剰設計を回避するためのコード。とにかくRESTはガイドラインにすぎません。
Victorio Berra
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.