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

我想要一些关于设计 REST API 的建议,它允许客户机有效地向一个集合添加/删除大量对象。

通过 API,客户端需要能够向集合中添加项,并从中删除项,以及操作现有项。在许多情况下,客户端希望对集合进行批量更新,例如添加1000个项目和删除500个不同的项目。感觉客户机应该能够在与服务器的单个事务中完成这项工作,而不是需要1000个单独的 POST 请求和500个 DELETE。

是否有任何关于实现这一目标的最佳实践或惯例的信息?

我目前的想法是,应该能够将一个对象表示对集合 URI 的更改,但这似乎与 HTTP 1.1 RFC不一致,HTTP 1.1 RFC似乎建议 PUT 请求中发送的数据应该独立于已经存在于 URI 中的数据进行解释。这意味着客户机必须一次性发送集合新状态的完整描述,这可能比更改大得多,甚至比客户机在发出请求时知道的更多。

显然,如果有必要,我很乐意偏离 RFC,但是如果存在这样的约定,我更愿意以传统的方式来做这件事。

23300 次浏览

你应该使用 AtomPub。它是专门为通过 HTTP 管理集合而设计的。甚至还可以为您选择的语言提供一个实现。

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

据我所知,REST 意味着 REST,所以你应该把状态从客户端传输到服务器端。

如果这意味着有太多的数据来来回回,也许您需要更改您的表示。CollectionChange 结构将通过一系列删除(通过 id)和添加(通过嵌入完整的 xml 表示形式) POST 到处理接口 URL 来工作。接口实现可以为删除和添加服务器端选择自己的方法。

最纯粹的版本可能是通过 URL 定义项,并且集合包含一系列 URL。新的集合可以在客户端更改后被 PUT,然后是一系列添加项的 PUT,如果您想从服务器中实际删除这些项,而不仅仅是从列表中删除它们,那么还可以进行一系列删除。

您可以引入现有集合元素的元表示,这些元素不需要传递它们的整个状态,因此在某些抽象代码中,您的更新可以如下所示:

{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}

添加(和修改)元素是通过定义它们的值来完成的,删除元素是通过不提及它来完成的,新的集合和重新排序元素是通过指定新的顺序来完成的(如果顺序完全存储的话)。

通过这种方式,您可以轻松地表示整个新集合,而不必重新传输整个内容。使用 If-Unmodified-Since头可以确保您对内容的想法确实与服务器的想法相匹配(这样您就不会意外地删除在请求提交时根本不知道的元素)。

您可能希望将更改任务本身视为一种资源。因此,您实际上是将一个对象放入其中,这是一个大容量数据更新对象。也许它有一个名称、所有者和需要解析和执行的 CSV、 XML 等的大块。在 CSV 的情况下,您可能还想确定 CSV 数据中表示的对象类型。

列出作业,添加作业,查看作业的状态,更新作业(可能是为了启动/停止它) ,删除作业(如果它正在运行就停止它)等等。这些操作很容易映射到 REST API 设计上。

一旦具备了这些,就可以轻松地添加批量数据更新程序可以处理的不同数据类型,甚至可以在同一任务中混合使用。换句话说,你不需要在你的应用程序中为你想导入的每种类型的东西复制相同的 API。

这也非常适合于后台任务实现。在这种情况下,您可能希望向单个任务对象添加字段,以允许 API 客户机指定它们希望如何被通知(一个 URL,它们希望您在完成任务时获取它,或者向它们发送电子邮件,等等)。

是的,PUT 创建/覆盖,但不部分更新。

如果需要部分更新语义,请使用 PATCH。

最好的办法是:

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