【问题标题】:Master/Detail with REST使用 REST 的主/详细信息
【发布时间】:2015-10-26 00:43:08
【问题描述】:

我确信这个主题之前一定已经被覆盖过,所以我很高兴有人指出我在搜索时可能错过的任何文章等。

我需要实现一个非常简单的 REST API 来添加和检索主/从关系中的记录。我的两个选项如下:

选项 1

POST /master
POST /master/[id]/details
GET  /master/[id]
GET  /master/[id]/details

优点

  • 感觉更“RESTful”
  • 可以检索细粒度数据以提高性能

缺点

  • 如果没有至少一个细节,大师就没有意义。如何处理原子性?如果添加时detail失败,在master上补偿DELETE?
  • 检索主/从集需要多次调用

选项 2

POST /master_and_details
GET  /master_and_details/[master id]

优点

  • 易于管理原子性

缺点

  • 管理更复杂的结构
  • GET 必须返回整个结构(并不总是有效)
  • 感觉不是很“RESTful”

谢谢, 约翰

【问题讨论】:

  • REST 或多或少决定了选项 1,选项 2 只是一个普通的旧 http api

标签: rest post get master-detail


【解决方案1】:

REST 或多或少规定了选项 1,选项 2 只是一个普通的旧 http api。

您说大师没有至少一个细节就毫无意义的说法可能是错误的。您不知道聪明的开发人员将来将如何使用您的 api。你可以猜到,但你不知道。

如果您自己确实需要复合解决方案,您始终可以在更高级别添加一个接口,该接口调用两个单独的接口并返回一个复合对象。

选项 1 允许实现微服务——或者至少,将关注点分离为两个可分离的对象。单独的选项 2 不会。

【讨论】:

  • 谢谢。了解开发人员可能会在未来某个时候独立使用这些资源。这种结构为此敞开了大门,但我仍然需要确保这种特殊用途的原子性。我可以按照您所说的编写一个包装器来编排桅杆和详细 POST,但如果它们失败,则需要进行补偿,这意味着需要 DELETE 服务。你会建议一个 DELETE 主和级联,还是最好的单独的 DELETE 服务?同样,单独的服务感觉更“RESTful”,但如果必须回滚多个详细记录,则需要更多的工作来补偿。谢谢。
  • 实际上,要正确执行此操作,您需要考虑的不仅仅是 api 是否宁静。你读过 Vaughn Vernon 的《实现领域驱动设计》吗? amazon.co.uk/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
【解决方案2】:

至少为了争论,并冒着我微薄的名声的风险,我会尝试第三种方法。

您将拥有两种资源:master 和 detail。 (不是“细节”,除非你想完全复数,在这种情况下你会有“大师”和“细节”)。 master 的表示将包括细节的集合,或者(更好)链接到细节的关系。考虑 https://www.rfc-editor.org/rfc/rfc6573 的链接关系。

因此,master 的 GET 包括(直接或间接通过关系)详细信息的集合。 master 的 POST/PUT 也可以通过他们在表单数据中的存在来 POST/PUT 详细成员。

任何细节也可以独立于主服务器进行 GET/PUT/POSTED。在这里,设计在一定程度上取决于细节是否有自己的主键,而不是使用带有主键的复合键。如果它有自己的主键,那么您可以:

GET /detail/{detailKey}  - gets specific detail
POST /detail  - creates new detail
GET /master/{masterkey}/detail  -- gets all details for master
GET /master{masterkey}/detail/{detailkey} -- get specific detail

显然,在 POST 上,数据必须包含 master 的 key。

您会看到用于获取详细信息的 URI 不止一个。我不认为这是错误的,但它确实引入了一些歧义:如果 detailKey 实际上不是 masterKey 的孩子,你是 404 吗?我会说是的。

如果明细使用复合键,则无法独立于主控进行 GET,因此无法支持上面显示的第一种形式。此外,在上面最后一个示例中使用的 {detailKey} 将是 master 中详细项目的标识符(通常是序列号)。

【讨论】:

    【解决方案3】:

    我肯定会选择 Option 1,因为 Option 2 与 REST 无关。但这并不意味着您需要使用多个查询来获取Master + Detail
    由于Detail 属于Master(所以它是其中的一部分),在我看来,在查询Master 时返回MasterDetail 是绝对可以的。
    您也可以考虑使用参数来控制是否发送Detail
    因此,您可以使用GET /master/1?detail=true,而不是执行GET /master/1
    对于POSTPUT 或多或少相同。只是没有查询参数,您的正文中有一个关于Detail 的“部分”。 使用 JSON 的示例:

    {
      "data": {
        "name": "master",
        "detail": [
          {
            "name": "detail1"
          },
          {
            "name": "detail2"
          }
        ]
      }
    }
    

    带有此数据的POST 可以创建一个带有name“master”的Master,并为此Master 创建2 个Details。

    正如@ElroyFlynn 之前所说,Details 也可以在没有Master 的情况下访问,如果这有意义的话。
    考虑一个有Threads 和Posts 的论坛。通常ThreadMaster,每个PostDetail。但是如果你想搜索最后一小时的所有Posts,你肯定想直接查询帖子(查询可能类似于GET /post?max_age=1h)。

    我也不同意,没有DetailMaster 没有意义。在某些情况下,它没有,但在论坛的情况下,Thread 本身就有意义。
    对于atomicity:
    这取决于具体情况:如果您删除 User,您通常会保留他的 Posts(即使在 StackOverflow 上也是如此)。如果你改为删除Thread,我猜,你可以删除Posts。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2012-11-17
      • 2014-04-13
      • 1970-01-01
      相关资源
      最近更新 更多