HTTP协议中有POST
和PATCH
方法用于部分更新。
在JSON API的PATCH
方法上,有RFC 5789,RFC 6902,RFC 7396。
但是我有一个针对大型资源的问题,需要在相当复杂的条件下进行部分更新。
让我们说我们有一个API端点"/members"
,它类似于具有数千个条目的大型集合,其中每个条目都有数十个字段。因此,客户可以通过"GET /members?fields=f1,f2,f3"
方法以分页方式部分读取这些值,并且每个客户仅读取对其当前任务必不可少的字段子集。
为简化问题,让我们假设任何条目都有一个必填"email"
字段用于标识和几个可选字段。
{
"email": "user@organization.com",
"optional1": "x",
"optional2": "x",
"optional3": "x"
}
我们有两个客户端并行工作,以批量创建和更新新记录。但是每个客户只希望覆盖其可选字段的子集。
因此,客户端A将发送带有A
值的批量补丁请求,仅由于该字段对于他们的任务必不可少,才允许覆盖"optional1"
字段值。该客户端还将为新条目的"optional2"
字段指定一个值。该客户根本没有指定"optional3"
字段。
{
"email": "user@organization.com",
"optional1": "A",
"optional2": "A"
}
虽然该记录是新记录,但它已完全写入存储中。
然后,客户端B将发送带有B
值的批量补丁请求,仅由于该字段对于他们的任务必不可少,才允许覆盖"optional2"
字段值。
{
"email": "user@organization.com",
"optional1": "B",
"optional2": "B",
"optional3": "B"
}
由于该记录已经存在,因此该记录的"optional1"
字段应保留相同的旧值A
,因为该字段不是必填字段,因此"optional2"
字段值应被覆盖新值B
,因为该字段必不可少,而"optional3"
字段值应接收值B
,因为该字段只是空的。
这些动作的合并结果应该如下。
{
"email": "user@organization.com",
"optional1": "A",
"optional2": "B",
"optional3": "B"
}
因此,行为取决于记录的存在。 你们将如何在JSON API可重用终结点方法中实现该条件,以对具有复杂条件的此类集合进行并发并行部分更新,如果该记录已经存在并且包含某些值,则该API的客户端只能覆盖该记录的一部分字段?
RFC 6902解决方案不匹配,因为它们的add
和replace
操作实际上都替换了一个值。
添加-如果目标位置指定了确实存在的对象成员,则该成员的值将被替换。
替换-“替换”操作将目标位置的值替换为新值。操作对象必须包含一个“值”成员,其内容指定替换值。
您可以看到它与Java Map.put()方法的匹配方式。
如果映射先前包含键的映射,则旧值将替换为指定值。
但是缺少的功能与Java Set.add()方法相匹配。
将指定的元素添加到该集中(如果尚不存在)(可选操作)。更正式地说,如果集合中不包含任何元素e2,则将指定的元素e添加到该集合中,使得(e == null?e2 == null:e.equals(e2))。如果此集合已经包含该元素,则调用将使该集合保持不变并返回false。
您将如何制作一个JSON API,以允许这两种类型的操作用于非常大的集合的批量修补程序,并且其中包含许多可选字段的元素?
感谢@ chad-jensen提供属性优先级规则的思想。 提到的文档提供了非常灵活的方法,因此我尝试根据自己的需要进行调整。我想我将有两个操作,优先级较低的“初始化”,以及优先级较高的“添加”或“替换”。
然后,在我的示例中,客户端A和客户端B发送的JSON数据如下。
客户端A
发送的数据,该数据以较低的优先级更新"optional2"
字段,并以最高的优先级更新"optional1"
字段。
{
"email": "user@organization.com",
"initialize":
{
"optional2": "A"
},
"replace":
{
"optional1": "A"
}
}
客户端B
发送的数据,该数据以较低优先级更新"optional1"
和"optional3"
字段,并以最高优先级更新"optional2"
字段。
{
"email": "user@organization.com",
"initialize":
{
"optional1": "B",
"optional3": "B"
},
"replace":
{
"optional2": "B"
}
}
答案 0 :(得分:0)
您将需要某种优先级映射,以决定每个客户端对哪些字段进行优先级排序。
似乎您已经拥有了,但是我将假定它存储在某个地方/服务器和/或客户端知道它们具有最高优先级(优先级)的字段。您可能还需要知道哪个客户端最后更新了每个字段。
话虽如此,您应该能够对每个属性执行null / empty / check,并且仅当它们是默认值(null / empty字符串)时才替换它们。在已经填充值的情况下,您将需要检查传入客户端的优先级是否高于上次更新该值的客户端。
我找到了一个文档,该文档可以阐明我的意思(它对某些第三方工具有一些具体说明,但其中存在概念):https://www.ibm.com/support/knowledgecenter/en/SSPLFC_7.2.0/UserGuide/c_cmdb_reconcilation_overview.html