web-dev-qa-db-ja.com

PUTまたはDELETEを使用してコレクションを部分的に変更しても問題ありませんか?

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

product-groups/123/products
  1. addをコレクションに追加する必要がある場合、some PUTの商品のみを渡してもよいですか?

  2. コレクションからsome商品を削除する必要がある場合、DELETEでfilter data(IDの配列)を渡しても問題ありませんか?

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

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

21
user151851

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

/products

たとえば、1つの製品を更新する場合、[〜#〜] put [〜#〜]/products/{id}に設定します。 (すべてのフィールドを更新するのではなく)1つの製品を部分的に更新する場合は、[〜#〜] patch [〜#〜]/products/{id}に使用することもできます。単一のエンティティの削除についても同様です([〜#〜] delete [〜#〜] to /products/{id})。

single ressourceをターゲットにしたい場合は、パスを使用して修飾しますsingle ressourceを変更したい場合。

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

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

例えば。赤である製品のサブセットを取得したい場合は、

[〜#〜] get [〜#〜] to /products?colour=red

したがって、これらすべてを削除する場合は、[〜#〜] delete [〜#〜]/products?colour=redを使用します。または、idを使用して一部の製品を削除する場合は、[〜#〜] delete [〜#〜]/products?id=1&id=2&id=3を使用できます。

一括作成リソースについてはどうですか? [〜#〜] post [〜#〜]あなたのコレクション[{...},{...},{...}]を単に/productsに。同じことが[〜#〜] put [〜#〜]および[〜#〜] patch [〜#〜]にも当てはまります。

それは本当に簡単です。

あなたの質問に答えるには:

コレクションに追加する必要がある場合、PUTを使用して一部の製品のみを渡してもよいですか?

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

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

それはオッケーです。 Eneko Alonsoが書いたように、時々bulkoperations "controller" -endpointsを介してカプセル化されます。つまり、[〜#〜] post [〜#〜]は(complex ) オペレーション。

11
Thomas Junk

通常、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の制限により空のボディを持つことを除いて))

5
Eneko Alonso

ちょうど以前の回答/コメントを正確に。

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

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

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

たとえば、要素をコレクションに追加するには、POST data to following URI:

https://example.com/products/

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

https://example.com/products/108/

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

3
Lukasz

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

  • PUTはcompleteの置き換えです。

    • シングルトン(/item/{id}など)にPUTし、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は、部分的な成功を伝えるための適切な方法を提供しません。適切なデフォルトは、全か無かの成功基準でトランザクションで操作を実行すると想定することです。これがあなたが望むものではなく、おそらくあなたはコレクションと直接対話するべきではありません。

2
claytond