在REST中,POST或PUT最适合upsert操作吗?

在REST中,POST或PUT最适合upsert操作吗?,rest,post,put,Rest,Post,Put,我在服务器中为客户端保留一个键值存储。如果用户发送密钥“k1”,那么我将其插入数据库。这被认为是POST还是PUT 我还有另一个操作,删除所有现有密钥并添加新密钥。这是POST还是PUT,因为它会清除记录并添加一个新记录。如果您混合所有内容,则可能没有执行REST。FromPOST和PUT具有不同的使用场景: 考虑 POST 将一张新的帖子张贴到一个博客上,放置改变现有的值。 应使用DELETE动词将删除作为一种独特的操作进行。因为在更新之前“全部删除”听起来不是个好主意。如果用户发送密钥“k1

我在服务器中为客户端保留一个键值存储。如果用户发送密钥“k1”,那么我将其插入数据库。这被认为是
POST
还是
PUT


我还有另一个操作,删除所有现有密钥并添加新密钥。这是
POST
还是
PUT
,因为它会清除记录并添加一个新记录。

如果您混合所有内容,则可能没有执行REST。From
POST
PUT
具有不同的使用场景:

考虑<代码> POST <代码>将一张新的帖子张贴到一个博客上,<代码>放置改变现有的值。

应使用
DELETE
动词将删除作为一种独特的操作进行。因为在更新之前“全部删除”听起来不是个好主意。

如果用户发送密钥“k1”,那么我会将其插入数据库。这算是邮寄还是邮寄。 根据报告:

PUT方法请求将封闭的实体存储在提供的请求URI下。如果请求URI引用的是一个已经存在的资源,则应将包含的实体视为驻留在源服务器上的实体的修改版本。如果请求URI不指向现有资源,并且该URI能够由请求用户代理定义为新资源,则源服务器可以使用该URI创建资源

因此,我认为使用PUT进行插入或更新是完全合法的,前提是在这两种情况下,URI都是事先知道的。如果将键用作URI的一部分(如中的k1),则应该是这样。然而,为了实现理想的RESTful,访问同一URL也应该允许您下载资源

另外,我还有一个操作,删除所有现有的密钥并添加新的密钥,这是POST还是PUT,因为它清除记录并添加新的密钥。 我不认为这个操作可以被认为是RESTful的,因为它做了两件事。它似乎提供了一个宏来满足特定客户机的需求,而不是简单地访问数据。标准的RESTful设计是

  • 通过向父URL发送GET来获取密钥列表。在上面的例子中,这将是
  • 通过向发送删除消息来删除这些密钥中的每一个
  • 通过向发送PUT来添加替换

  • 不太清楚,但我认为通过向发送单个删除请求来删除所有资源也是合法的。

    upsert操作背后的思想是,客户机拥有关于/决定数据结构的信息,并发送带有键值的数据。因此,upsert操作的请求模型与update操作非常相似,包括键,如下例所示:

    /customers/jimmy
    
    POST /customers HTTP/1.1
    Content-Type: ...
    Content-Length: ...
    Host: server.yourdomain.com
    Accept: ...
    User-Agent: ...
    
    id      jimmy
    name    jimmy
    Occupation   Stackoverflower
    
    将放置更新现有记录的预期方法。所以你的选择应该放在第一位

    POST通常用于插入具有全新内容的新记录,如以下示例所示:

    /customers/jimmy
    
    POST /customers HTTP/1.1
    Content-Type: ...
    Content-Length: ...
    Host: server.yourdomain.com
    Accept: ...
    User-Agent: ...
    
    id      jimmy
    name    jimmy
    Occupation   Stackoverflower
    
    所以在您的情况下,您不需要任何POST操作,因为PUT for upsert操作也涵盖了这一点


    这里,有关upsert的关键问题是,您在upsert操作方面信任客户的可能性有多大。如果客户机希望使用现有密钥插入新记录,会发生什么情况?在您的情况下,应该将此请求作为更新处理,因为插入和更新请求都指向同一个api,并且您有一个现有记录。关于设计,这是您需要回答的问题。

    Polly Shaw的回答是正确的,但我想指出的是,考虑到消息很可能不完整(在尚未创建资源时缺少ID),使用修补程序动词会稍微正确一些


    这是非常精细的调整。

    如果upsert的定义是新记录与现有记录的混合(要更新)

    提及:

    PUT必须是幂等的。这意味着,如果再次放置相同的有效负载,则不应更改系统状态

    如果预期的有效负载是新的和现有的混合,并且预期的行为是在第二次创建更多的新记录,那么它看起来“upsert”将与POST更紧密地对齐

    我们努力创建容错API。如果不能使PUT幂等元,而他们必须使用它,则可能会损坏系统。另一方面,POST不应是幂等的,因此,如果您在有效负载中发送仅更新数据(一次又一次)(即使这在技术上违反了POST的幂等规则,因为它没有通过在后续调用中添加记录来更改系统的状态),则系统(可能)不会损坏

    • 规范中说PUT“可以”添加新项,“必须”是幂等的
    • 它说POST“必须”添加新项,并且不是幂等项
    如果你真的想实现upsert,两者都不是完美的,但是如果错误导致PUT上的损坏,API应该受到谴责(它应该是幂等的),而POST上的损坏是“我告诉过你的”

    我也喜欢思考API消费者将寻找什么。通常,在新屏幕上工作的UI开发人员会希望添加用户在UI中添加的记录。他将首先寻找一个帖子,然后发现它也处理了等式的PUT端


    因此,两者都不是,但如果必须选择,请选择POST。

    我确实认为在某些情况下“upsert”是有效的,例如,如果用户“查看”了某个资源,则会进行标记,即我希望此“标记/选中/勾选”,而不管它以前的状态如何。对于5张反对票,此答案有什么问题?调用者可能会根据结果调用get,然后调用put或post。@RuntimeException我想这是因为,在upsert时(当一个端点应该更新一个资源,但如果该资源不存在,则创建该资源)会告诉我们同样的问题,并询问不同的场景。所以,它并没有回答问题,而是告诉了同样的事情,这已经很清楚了。@RuntimeException,也有点误导性地等同于