在单个请求中批量创建或更新

让我们假设有两个资源BinderDoc关联关系,这意味着DocBinder独立存在。 Doc可能或可能不属于BinderBinder可能是空的。

如果我想设计一个允许用户发送Doc集合的REST API,请在IN A SINGLE REQUEST中 ,如下所示:

{
  "docs": [
    {"doc_number": 1, "binder": 1}, 
    {"doc_number": 5, "binder": 8},
    {"doc_number": 6, "binder": 3}
  ]
}

对于文档中的每个docs

  • 如果doc存在,则将其分配给Binder
  • 如果doc不存在,请创建它并分配它
  • 我很困惑这应该如何实施。

  • 使用什么HTTP方法?
  • 必须返回哪些响应代码?
  • 这是否适合REST?
  • URI的外观如何? /binders/docs
  • 处理批量请求时,如果有几个项目出现错误,但另一个项目出现则会怎样。 必须返回哪些响应代码? 批量操作应该是原子的吗?

  • 我认为你可以使用POST或PATCH方法来处理这个问题,因为它们通常是为此而设计的。

  • 使用POST方法通常用于在列表资源上使用时添加元素,但您也可以支持该方法的多个操作。 请参阅此答案:如何更新REST资源集合。 您还可以支持输入的不同表示格式(如果它们对应于数组或单个元素)。

    在这种情况下,没有必要定义格式来描述更新。

  • 使用PATCH方法也是合适的,因为相应的请求对应于部分更新。 根据RFC5789(http://tools.ietf.org/html/rfc5789):

    扩展超文本传输​​协议(HTTP)的几个应用程序需要一个功能来执行部分资源修改。 现有的HTTP PUT方法只允许完整替换文档。 该建议添加了一个新的HTTP方法PATCH来修改现有的HTTP资源。

    在这种情况下,你必须定义你的格式来描述部分更新。

  • 我认为在这种情况下, POSTPATCH非常相似,因为您并不需要描述每个元素的操作。 我会说这取决于发送的表示的格式。

    PUT的情况有点不太清楚。 事实上,当使用PUT方法时,你应该提供整个列表。 事实上,请求中提供的表示将替代列表资源之一。

    您可以有两个有关资源路径的选项。

  • 使用doc列表的资源路径
  • 在这种情况下,您需要在请求中提供的表示中明确提供文档链接和活页夹。

    以下是此/docs的示例路由。

    这种方法的内容可以用于POST方法:

    [
        { "doc_number": 1, "binder": 4, (other fields in the case of creation) },
        { "doc_number": 2, "binder": 4, (other fields in the case of creation) },
        { "doc_number": 3, "binder": 5, (other fields in the case of creation) },
        (...)
    ]
    
  • 使用binder元素的子资源路径
  • 此外,您还可以考虑利用子路线来描述文档和活页夹之间的链接。 关于文档和联编程序之间关联的提示现在不需要在请求内容中指定。

    以下是此/binder/{binderId}/docs的示例路由。 在这种情况下,使用POSTPATCH方法发送文档列表会在创建文档(如果不存在)后将文档附加到具有标识符binderId文档夹。

    这种方法的内容可以用于POST方法:

    [
        { "doc_number": 1, (other fields in the case of creation) },
        { "doc_number": 2, (other fields in the case of creation) },
        { "doc_number": 3, (other fields in the case of creation) },
        (...)
    ]
    

    关于答复,您应该定义答复的等级和要返回的错误。 我看到两个级别:状态级别(全局级别)和有效负载级别(更薄级别)。 您也可以定义与您的请求相对应的所有插入/更新是否必须是原子的。

  • 原子
  • 在这种情况下,您可以利用HTTP状态。 如果一切顺利,你会得到200的状态。 如果不是,如果提供的数据不正确(例如binder ID无效)或其他的状态,则为400

  • 非原子
  • 在这种情况下,状态200将被返回,并由响应表示来描述所做的事情以及错误最终发生的位置。 ElasticSearch在其REST API中有一个用于批量更新的端点。 这可以给你在这个级别的一些想法:http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/bulk.html。

  • 异步
  • 您还可以实施异步处理来处理提供的数据。 在这种情况下,HTTP状态返回将是202 。 客户端需要额外的资源来查看会发生什么。

    在完成之前,我还希望注意到OData规范解决了与具有名为导航链接的功能的实体之间的关系问题。 也许你可以看看这个;-)

    以下链接也可以帮助您:https://templth.wordpress.com/2014/12/15/designing-a-web-api/。

    希望它能帮助你,蒂埃里


    您可能需要使用POST或PATCH,因为更新和创建多个资源的单个请求不太可能是幂等的。

    PATCH /docs绝对是一个有效的选择。 你可能会发现使用标准补丁格式对你的特定场景很棘手。 不确定这一点。

    你可以使用200.你也可以使用207 - 多状态

    这可以通过RESTful方式完成。 在我看来,关键是要有一些资源用于接受一组更新/创建的文档。

    如果你使用PATCH方法,我认为你的操作应该是原子的。 即我不会使用207状态码,然后在响应主体中报告成功和失败。 如果你使用POST操作,那么207方法是可行的。 您将不得不设计自己的响应主体来通信哪些操作成功,哪些失败。 我不知道一个标准化的。


    PUT ing

    PUT /binders/{id}/docs创建或更新,并将单个文档与活页夹相关联

    例如:

    PUT /binders/1/docs HTTP/1.1
    {
      "docNumber" : 1
    }
    

    补丁

    PATCH /docs如果文档不存在并将其与粘合剂关联,则创建文档

    例如:

    PATCH /docs HTTP/1.1
    [
        { "op" : "add", "path" : "/binder/1/docs", "value" : { "doc_number" : 1 } },
        { "op" : "add", "path" : "/binder/8/docs", "value" : { "doc_number" : 8 } },
        { "op" : "add", "path" : "/binder/3/docs", "value" : { "doc_number" : 6 } }
    ] 
    

    稍后我会提供更多见解,但同时如果您愿意,请参阅RFC 5789,RFC 6902和William Durand的Please。 不要修补像Idiot博客条目。

    链接地址: http://www.djcxy.com/p/71447.html

    上一篇: Bulk Create or Update in single request

    下一篇: Type Header and Derive Type from URL