PUTまたはDELETEでコレクションを部分的に変更しても大丈夫ですか?


21

製品グループに製品のコレクションがあります。例:

product-groups/123/products
  1. コレクションに追加する必要がある場合、PUTを使用して一部の製品のみを渡すことはできますか?

  2. コレクションからいくつかの製品を削除する必要がある場合、フィルターデータ(IDの配列)をDELETEで渡しても大丈夫ですか?

ReSTの精神で機能を実装する最良の方法は何ですか?

編集:アイテムは個別のエンティティ、基本的には製品のIDへのリンクです。


製品グループのアイテムは、別の場所で管理される個別のリソースですか?または、それらは製品グループコレクションの一部にすぎませんか?別の場合、製品は複数の製品グループに属することができますか?
マーティンピーターズ

2
おそらくPATCH この仕様は、リソースに部分的な変更を適用するために使用される新しいHTTP / 1.1 [RFC2616]メソッドPATCHを定義します。
エサイリヤ

製品(ID)は複数の製品グループに属することができます。
user151851

コレクション内の製品を追加または削除する方法をパッチする方法を言うためのよく知られた方法(ベストプラクティス)はありますか?
user151851

回答:


10

一般に、xのコレクション全体を表す1つのエンドポイントがあります。

/products

単一の製品を更新する場合、PUTをにしたとし/products/{id}ます。(すべてのフィールドを更新するのではなく)単一の製品を部分的に更新する場合は、PATCHを使用することもできます/products/{id}。同じことが、単一のエンティティの削除(DELETE to /products/{id})にも当てはまります。

単一のリソースを対象とする場合は、パスを介して修飾し、変更する単一のリソースを限定します。

スキームを破る唯一のアクションは、リソースの作成です。リソースを作成するときは、コレクション全体をターゲットにします。たとえばPOSTを使用し/productsます。

ただし、コレクション全体に影響する操作のターゲットは、適切なコレクションエンドポイントに移動する必要があることは明らかです。

たとえば、赤の製品のサブセットを取得するには、次の方法で要求します。

行き/products?colour=redます。

したがって、これらすべてを削除する場合は、DELETEし /products?colour=redます。それとも、経由で製品の一部を削除したい場合はid、あなたが可能性があり、DELETE /products?id=1&id=2&id=3

リソースの一括作成についてはどうですか?コレクションを単にに投稿します。同じことがPUTPATCHにも当てはまります。[{...},{...},{...}]/products

それは本当に簡単です。

質問に答えるには:

コレクションに追加する必要がある場合、PUTで​​一部の製品のみを渡すことは問題ありませんか?

それは大丈夫なだけでなく、そのようにすることをお勧めします。

コレクションからいくつかの製品を削除する必要がある場合、DELETEでフィルターデータ(IDの配列)を渡しても問題ありませんか?

それは大丈夫です。Enekoアロンソが書いたように、時にはあるbulkoperationsすなわちA「コントローラ」-endpointsを介してカプセル化されたPOSTをトリガー(複合)操作に使用されます。


2
PUTは置換操作です。「一部の製品」を使用してコレクションエンドポイントでPUTを呼び出すと、「一部の製品」のリストに含まれていないすべての製品を削除(OPの場合、関係を削除)する必要があります。アイテムの追加に使用できますが、OPが期待するものではないアイテム(私の意見では)も削除する必要があります。それに応じて、最初の質問に対する回答を修正する必要があります。
クレイトン

@claytond:で部分的な更新が行われPATCH、完全な置換がで行われる限り、答えは問題ないと思いますPUT
9000

4
@ 9000。もちろん、現在の答えは、「コレクションに追加することをお勧めします... PUTを使用して一部の製品のみを渡すこと」です。それは確かに間違っています。POSTを奨励しました。PUTが可能...ただし、すべて(一部ではない)のアイテムを渡すことによってのみ。
クレイトン

5

通常、RESTメソッドは、単一のエンティティ/オブジェクト(CRUD)を操作することを目的としています。

いくつかのオプションがあります:

  • コレクションをエンティティとして扱い、POSTを介してコレクションを更新します
  • 代替の非REST操作を作成する

最初のものはREST標準に従いますが、コレクションオブジェクト/エンティティが非常に大きくなる可能性があるため、コストがかかる可能性があります(1つの製品を追加/削除するためだけに数千の製品を持つグループを更新することは、大きな要求になります)。

2番目のオプションは、CRUD操作を超えてRESTを拡張する方法として、多くのAPIで好まれています。

例えば:

GET product-groups/123/products (list all the products in the group)
POST product-groups/123/products/append (POST a list of new product ids to append to the group)
POST product-groups/123/products/remove (POST a list of product ids to remove from the group)

多くのAPIは、この拡張操作に常にPOSTを使用しますが、他のhttpメソッドの使用を制限するものはありません(GETとDELETEの制限が空の本体を持つこと以外)


確かに、目標を達成するにはいくつかの方法があります。どれがベストプラクティスですか?どちらがより将来性がありますか?
user151851

4
@ user151851:完全なREST準拠(そのようなことがある場合)は、高い目標です。ここでのアプローチの概要は、「現実の世界」で実際に使用されているアプローチを採用しようとしているため、本質的に事実上の標準になっているため、より現実的です。それは、あなたが手に入れようとしているのとほぼ同じくらい将来的なものです。
ロバートハーベイ

2
URLに「追加」と「削除」を使用してカスタム動詞を導入しませんか?そのようにして、APIの使用方法を説明する必要があります。持っているもの、つまりHTTPメソッドを再利用すべきではないでしょうか?その場合、アクションはよく知られています。
user151851

7
この答えに出くわした他の人にとって:それは間違っています。@ user151851が述べたように、これはURLに動詞を導入します。実際の質問に関しては、私は良い答えがありませんが、これはそうではありません。
umbrae

「拡張」products/collectionは、アイテムの「エンベロープ」を返し、PUTを介して変更されたエンベロープの内容を作成することで、よりリソース指向にすることができますか?「コレクション内のアイテムを正確にどのようにしたいのか」などです。
ルークププレット16年

3

前の回答/コメントを正確に。

私の知る限り、POSTはコレクションに単一の要素を追加する方法です。

DELETEは、コレクションから単一の要素を削除するメソッドです。両方のシナリオは完全にRESTfulです。

ただし、適切なURIを使用して、単一の要素またはコレクション全体を参照する必要があります。

たとえば、コレクションに要素を追加するには、次のURIにデータをPOSTする必要があります。

https://www.factory.net/products/

コレクションから単一の製品を削除するには、次のようなリクエストを送信するDELETEメソッドを使用できます。

https://www.factory.net/products/108/

PATCHメソッドを使用して、コレクション内のいくつかの要素を更新できます。たとえば、1つの要素の1つのフィールドのみを更新する必要がある場合。非常に大きなコレクションに対して完全なリソース表現をPUTすることは、非常にコストのかかる操作になる可能性があります。


2

原則として、すべてのRESTful操作はコレクションで有効ですが、動詞のセマンティクスがコレクションにどのように適用されるかを理解してください。

  • PUTは完全な代替品です。

    • あなたはシングルトン(例えばに置く場合/item/{id})と残しnameて、それがクリアされるか、nullまたは類似したものに設定する必要があります。
    • コレクションにPUTし、アイテムを含めない場合、そのコレクションから削除する必要があります。

    PUTを使用してアイテムを追加できますが、「すべて」のアイテムを送信する必要があります。「一部」のアイテムを送信すると、削除されるはずです(これはOPが望んでいるものではないと思います)。

  • DELETEはより直感的です。コレクションまたはそのフィルター処理されたサブセットを削除することは有効です。フィルターに含まれるアイテムのみが影響を受けます。

  • PATCHも有効です。理論的には、「操作」のリストを提供することになっています。たとえば、次のように技術的に送信する必要があります。

    [{ 
        "action": "update",
        "id": <id>,
        "value": {...}
    },{
        "action": "add",
        "value": {...}
    }, ...]
    

    実際には、各アイテムがUPSERT(更新または挿入)ロジックを使用して処理されるオブジェクトの部分的なリストを受け入れるAPIを見るのがより一般的です。

  • 技術的には、POSTは入力を「リソースの固有のセマンティクスに従って」処理する必要があります。

    • 実際には、POSTは通常「作成」操作に使用されます。
    • ただし、POSTは非標準の呼び出しに使用される動詞でもあります。アクションエンドポイントが厳密にRESTfulであるかどうかについては活発な議論がありますが(「いいえ」の側)、のようなエンドポイントにリクエストを送信する場合はPOSTが適切な動詞です{resource}/activate

注:コレクションで非GET操作を使用する場合は、成功と失敗の定義を慎重に検討してください。RESTは、部分的な成功を伝える良い方法を提供しません。適切なデフォルトは、成功または失敗の条件をすべて満たしたトランザクションで操作を実行すると想定することです。これが望んでいない場合は、おそらくコレクションと直接対話しないでください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.