在RESTful API中,DELETE调用应该是递归的吗?

8
假设我有以下关系型数据结构(举个例子):

(for example sake)

A `post` which is a child of a `category`

这些API端点可以访问这些数据:
  • GET /category/1
  • GET /category/1/post/1
  • GET /category/1/post/2
现在我决定使用我的API来删除类别1,因此我运行DELETE /category/1
然而,类别1有关联的子文章元素,如果没有这个类别就无法存在,你会期望这个调用会失败并说你必须先删除子元素,或者在删除类别时自动递归删除子元素吗?

1
这取决于帖子是否需要至少一个类别。如果不需要,它们可以独立存在而无需类别,因此您无需删除它们或其评论。如果它们需要一个类别,则需要删除该类别中的所有帖子和评论。评论不能没有帖子存在,因此如果您删除了帖子,则需要删除该帖子的所有评论,但是帖子是否可以在没有类别的情况下存在取决于您的领域模型。 - codebrane
1
你说它是递归的意义是什么?因为递归性是一种实现细节,客户端不应该关心它。因为如果你在RDBMS上进行基本的CRUD实现,你很可能会级联删除,所以成功案例在一般情况下大多是预期行为。但所有这些也取决于您的业务需求。 - Abhishek Nair
1
我不太明白你的问题是什么。但是,如果你能调用 GET /category/1(获取所有),那么你也应该能够调用 DELETE /category/1(删除所有)。 - dieter
1
你的问题没有意义,因为实现细节取决于你和你特定的使用情况。你可以删除所有相关记录,或者如果父记录有子元素则抛出400。但这仅取决于你,REST不强制执行任何规定。 - Mike Doe
1
我会设计一个机制,只有在删除所有相关文章之后才允许删除类别。这意味着根据类别的状态发送适当的“ALLOW”头。为了删除类别中的所有文章,我会创建一个更详细的端点,比如“DELETE posts?filter=category:1”。请参见我的答案以获取更多详细信息 https://dev59.com/Fajka4cB1Zd3GeqPBqLI#49118002 - jschnasse
显示剩余5条评论
4个回答

3

在我看来,这更多是一个设计决策,没有错误的做法。因此,所有取决于需求。

如果您决定删除类别会删除所有子帖子元素,则可以以多种方式执行此操作(按我的首选顺序排序)。

  • 在数据库中控制级联删除。
  • 在数据访问层(DAL)中添加代码,以便在调用类别时删除该类别下的所有帖子。

如果您决定不对子帖子执行“级联”删除,则您唯一的选择是返回适当的错误消息,说明为什么无法删除该类别。

如果您希望通过执行以下操作之一使Web服务调用更加清晰,请这样做。

DELETE /category/1?includePost=true --> 删除第1个类别和其下的所有帖子。

DELETE /category/1 --> 删除第1个类别或如果无法删除则返回错误信息。


2

当你使用DELETE删除类别时,我认为它应该成功。

假设它失败了-那么你需要使用GET获取所有帖子和评论,然后使用DELETE迭代它们-这有什么意义呢?

另外,我会使用复数名词来命名资源,例如:

GET /categories/1/posts

获取所有帖子时,看起来更加一致。但是,如何实现取决于您,是使用级联还是不使用级联 - 看看哪种更适合您的需求。

1

1. 命名

  • 我会使用复数形式/categories/posts/comments
  • 在我看来,/categories 不是一个好的名称,因为它允许从数据库中递归删除大量实体。我会使用像 /sections/areas/partitions 这样的名称。
  • 你可以提供类似于 DELETE /categories 的东西,比如
  • DELETE /posts?filter=category:1

2. 路由

我会考虑使用更加扁平化的结构来处理 http 路由,并为每个实体创建独立的端点。

为以下内容提供 CR(创建、读取):

GET,POST /categories
GET,POST /posts
GET,POST /comments 

然后为单个实体提供RUD(读取、更新、删除)功能。

GET,PUT,DELETE /categories/1
GET,PUT,DELETE /posts/1
GET,PUT,DELETE /comments/4

在我看来,这样做可以使使用更加直观,而且不会暗示任何层级或特定行为。现在像适当的那样,在每个实体上定义DELETE3. 实施 示例
  • DELETE /posts?filter=category:1

    删除所有属于分类 ID 为 1 的帖子。

  • DELETE /categories/1

    • 如果 /categories/1 是空的

      只删除一个类型为 category 的实体。

    • 如果 /categories/1 不为空

      返回 HTTP 405 Method Not Allowed 并要求用户先运行 DELETE /posts?filter=category:1 来清空 /categories/1

  • OPTIONS categories/1
    • 如果 categories/1 是空的

      设置 ALLOW 为 GET、...、DELETE

    • 如果 categories/1 不为空

      设置 ALLOW 为 GET、...(不允许 DELETE

  • DELETE /posts/1

    删除帖子及所有引用它的评论,或者使用与 DELETE categories/1 相同的模式。

  • DELETE /comments/1

    仅删除该评论。

4. 查找更多信息

当无法删除特定原因时返回哪个HTTP状态码?


-1

你可以在Rest中执行以下操作:

"methods": [ "GET", "POST", "PUT", "PATCH", "DELETE" ],

我可以通过DELETE /categories/1/post 来进行此操作,所以命名应该遵循规范。


你是说你期望 DELETE /categories/1/post 删除该类别中的所有帖子,以便 OP 可以删除该类别吗?这可能与原始删除具有相似的级联效果。 - Rup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接