简体   繁体   English

通过 REST (RESTful) API 进行批量集合操作

[英]Bulk Collection Manipulation through a REST (RESTful) API

I'd like some advice on designing a REST API which will allow clients to add/remove large numbers of objects to a collection efficiently.我想要一些关于设计 REST API 的建议,它允许客户端有效地向集合添加/删除大量对象。

Via the API, clients need to be able to add items to the collection and remove items from it, as well as manipulating existing items.通过 API,客户端需要能够将项目添加到集合中并从中删除项目,以及操作现有项目。 In many cases the client will want to make bulk updates to the collection, eg adding 1000 items and deleting 500 different items.在许多情况下,客户端希望对集合进行批量更新,例如添加 1000 个项目并删除 500 个不同的项目。 It feels like the client should be able to do this in a single transaction with the server, rather than requiring 1000 separate POST requests and 500 DELETEs.感觉客户端应该能够在与服务器的单个事务中完成此操作,而不是需要 1000 个单独的 POST 请求和 500 个 DELETE。

Does anyone have any info on the best practices or conventions for achieving this?有没有人有关于实现这一目标的最佳实践或约定的任何信息?

My current thinking is that one should be able to PUT an object representing the change to the collection URI, but this seems at odds with the HTTP 1.1 RFC , which seems to suggest that the data sent in a PUT request should be interpreted independently from the data already present at the URI.我目前的想法是,应该能够 PUT 一个表示集合 URI 更改的对象,但这似乎与HTTP 1.1 RFC不一致,这似乎表明 PUT 请求中发送的数据应该独立于URI 中已经存在的数据。 This implies that the client would have to send a complete description of the new state of the collection in one go, which may well be very much larger than the change, or even be more than the client would know when they make the request.这意味着客户端必须一次性发送集合的新状态的完整描述,这很可能比更改大得多,甚至比客户端发出请求时所知道的还要多。

Obviously, I'd be happy to deviate from the RFC if necessary but would prefer to do this in a conventional way if such a convention exists.显然,如果有必要,我很乐意偏离 RFC,但如果存在这样的约定,我更愿意以传统方式执行此操作。

You might want to think of the change task as a resource in itself.您可能希望将更改任务本身视为一种资源。 So you're really PUT-ing a single object, which is a Bulk Data Update object.因此,您实际上是在 PUT 处理单个对象,即批量数据更新对象。 Maybe it's got a name, owner, and big blob of CSV, XML, etc. that needs to be parsed and executed.也许它有一个名称、所有者和需要解析和执行的 CSV、XML 等大块。 In the case of CSV you might want to also identify what type of objects are represented in the CSV data.对于 CSV,您可能还想确定 CSV 数据中表示的对象类型。

List jobs, add a job, view the status of a job, update a job (probably in order to start/stop it), delete a job (stopping it if it's running) etc. Those operations map easily onto a REST API design.列出作业、添加作业、查看作业状态、更新作业(可能是为了启动/停止它)、删除作业(如果它正在运行则停止它)等。这些操作很容易映射到 REST API 设计。

Once you have this in place, you can easily add different data types that your bulk data updater can handle, maybe even mixed together in the same task.完成此操作后,您可以轻松添加批量数据更新程序可以处理的不同数据类型,甚至可以在同一任务中混合在一起。 There's no need to have this same API duplicated all over your app for each type of thing you want to import, in other words.换句话说,无需为您要导入的每种类型的内容在整个应用程序中复制相同的 API。

This also lends itself very easily to a background-task implementation.这也很容易用于后台任务实现。 In that case you probably want to add fields to the individual task objects that allow the API client to specify how they want to be notified (a URL they want you to GET when it's done, or send them an e-mail, etc.).在这种情况下,您可能希望向各个任务对象添加字段,以允许 API 客户端指定他们希望如何收到通知(他们希望您在完成后获取的 URL,或向他们发送电子邮件等) .

Yes, PUT creates/overwrites, but does not partially update.是的,PUT 创建/覆盖,但不会部分更新。

If you need partial update semantics, use PATCH.如果您需要部分更新语义,请使用 PATCH。 See http://greenbytes.de/tech/webdav/draft-dusseault-http-patch-14.html .请参阅http://greenbytes.de/tech/webdav/draft-dusseault-http-patch-14.html

You should use AtomPub .您应该使用AtomPub It is specifically designed for managing collections via HTTP.它专为通过 HTTP 管理集合而设计。 There might even be an implementation for your language of choice.甚至可能有您选择的语言的实现。

至少对于 POST,您似乎应该能够 POST 到列表 URL 并让请求正文包含新资源列表而不是单个新资源。

As far as I understand it, REST means REpresentational State Transfer, so you should transfer the state from client to server.据我了解,REST 意味着 REpresentational State Transfer,因此您应该将状态从客户端传输到服务器。

If that means too much data going back and forth, perhaps you need to change your representation.如果这意味着来回传递的数据过多,那么您可能需要更改表示形式。 A collectionChange structure would work, with a series of deletions (by id) and additions (with embedded full xml Representations), POSTed to a handling interface URL.一个 collectionChange 结构可以工作,通过一系列删除(通过 id)和添加(带有嵌入的完整 xml 表示),发布到处理接口 URL。 The interface implementation can choose its own method for deletions and additions server-side.接口实现可以选择自己的方法进行删除和添加服务器端。

The purest version would probably be to define the items by URL, and the collection contain a series of URLs.最纯粹的版本可能是通过 URL 定义项目,并且集合包含一系列 URL。 The new collection can be PUT after changes by the client, followed by a series of PUTs of the items being added, and perhaps a series of deletions if you want to actually remove the items from the server rather than just remove them from that list.新集合可以在客户端更改后进行 PUT,然后是一系列添加的项目的 PUT,如果您想从服务器中实际删除项目而不是仅仅从该列表中删除它们,则可能进行一系列删除。

You could introduce meta-representation of existing collection elements that don't need their entire state transfered, so in some abstract code your update could look like this:您可以引入不需要整个状态转移的现有集合元素的元表示,因此在一些抽象代码中,您的更新可能如下所示:

{existing elements 1-100}
{new element foo with values "bar", "baz"}
{existing element 105}
{new element foobar with values "bar", "foo"}
{existing elements 110-200}

Adding (and modifying) elements is done by defining their values, deleting elements is done by not mentioning it the new collection and reordering elements is done by specifying the new order (if order is stored at all).添加(和修改)元素是通过定义它们的值来完成的,删除元素是通过不提及它来完成的,新集合和重新排序元素是通过指定新顺序来完成的(如果顺序已存储)。

This way you can easily represent the entire new collection without having to re-transmit the entire content.通过这种方式,您可以轻松呈现整个新集合,而无需重新传输整个内容。 Using a If-Unmodified-Since header makes sure that your idea of the content indeed matches the servers idea (so that you don't accidentally remove elements that you simply didn't know about when the request was submitted).使用If-Unmodified-Since标头可确保您对内容的想法确实与服务器的想法相匹配(这样您就不会意外删除您在提交请求时根本不知道的元素)。

Best way is :最好的方法是:

Pass Only Id Array of Deletable Objects from Front End Application To Web API
    2. Then You have Two Options: 
       2.1 Web API Way : Find All Collections/Entities using Id arrays and Delete in API , but you need to take care of Dependant entities like Foreign Key Relational Table Data too
     2.2. Database Way : Pass Ids to your database side, find all records in Foreign Key Tables and Primary Key Tables and Delete in same order i.e. F-Key Table records then P-Key Table records

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM