在没有主键的情况下更新记录的 REST 方法是什么?

What is the REST way to update a record without primary key?

我创建了一个 REST API。根据我的设计,我们必须 每天 .

存储用户的血糖水平

问题是:


例如,如果我打这个电话

POST https://{host}/users/1/blood-sugar/

{
    "measureDate": "2019-05-04",
    "bloodSugarLevel": 86
}

它将创建一个 blood-sugar 资源,数据库将分配 ID(假设 ID=333

没关系到这里。

然后,我希望能够在相同日期但血糖水平不同的情况下提出第二个请求。结果,我希望后端应该找到以前的 blood-sugar 资源(ID=333)并更新 bloodSugarLevel 字段,因为我们已经有了这一天的记录(2019-05-04).我不想在请求正文或 URI 中发送 ID=333

POST https://{host}/users/1/blood-sugar/

{
    "measureDate": "2019-05-04",
    "bloodSugarLevel": 105 # only this value is different
}

我的问题是:

有什么方法可以用 REST 实现这个(或类似的)结果吗?您可以让我更改 VERB 或 URI 或请求正文。

Note: If I was doing this with WCF or similar thing, only single method would satisfy the all my requirements. For example: CreateOrUpdateBloodSugarLevel(int userId, DateTime measureDate, int bloodSugarLevel)

谢谢。

Is there any way to achieve this (or similar) result with REST?

只需 POST 将更新后的值发送到同一端点就可以了。

想想你将如何在万维网上做到这一点。您将访问一个网站,并加载一些表单,其中包含一个日期文本字段、一个 bloodSugarLevel 文本字段和一个提交按钮。这会 POST 将消息发送到 Web 服务器,您的浏览器会返回一些响应。

请注意,作为客户端,我们真的不关心服务器是否将新消息附加到列表中,或者将消息更新插入到映射中,或者使用 RDBMS 或图形数据库做一些聪明的事情。这些是实施细节;拥有统一接口的部分意义在于,接口意味着客户端(和通用组件)实际上不需要知道发生了什么。

另一个可行的应用程序协议是将 bloodSugarLevel 视为用户可以在本地编辑的文档。这样,客户端就可以使用任何支持 HTTP 的编辑器来做正确的事情。

GET /users/1/blood-sugar/

200 OK

{
    "measureDate": "2019-05-03",
    "bloodSugarLevel": 90
}

PUT /users/1/blood-sugar/
{
    "measureDate": "2019-05-04",
    "bloodSugarLevel": 86
}

204 No Content

PUT /users/1/blood-sugar/
{
    "measureDate": "2019-05-04",
    "bloodSugarLevel": 105
}

当网络不可靠时使用 PUT 有一些语义优势;因为服务器同意消息处理将以幂等方式完成,所以客户端可以通过重复发送来响应等待确认的超时。

语义上,PUT 表示“upsert”,但底层 实现 不一定是 upsert。我们只承诺客户可以期望的语义。