如何通过JSON API实现复杂的条件批量批量更新?

时间:2018-09-27 15:54:48

标签: java json rest api http-patch

HTTP协议中有POSTPATCH方法用于部分更新。 在JSON API的PATCH方法上,有RFC 5789RFC 6902RFC 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解决方案不匹配,因为它们的addreplace操作实际上都替换了一个值。

  

添加-如果目标位置指定了确实存在的对象成员,则该成员的值将被替换。

     

替换-“替换”操作将目标位置的值替换为新值。操作对象必须包含一个“值”成员,其内容指定替换值。

您可以看到它与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"
    }
}

1 个答案:

答案 0 :(得分:0)

您将需要某种优先级映射,以决定每个客户端对哪些字段进行优先级排序。

似乎您已经拥有了,但是我将假定它存储在某个地方/服务器和/或客户端知道它们具有最高优先级(优先级)的字段。您可能还需要知道哪个客户端最后更新了每个字段。

话虽如此,您应该能够对每个属性执行null / empty / check,并且仅当它们是默认值(null / empty字符串)时才替换它们。在已经填充值的情况下,您将需要检查传入客户端的优先级是否高于上次更新该值的客户端。

我找到了一个文档,该文档可以阐明我的意思(它对某些第三方工具有一些具体说明,但其中存在概念):https://www.ibm.com/support/knowledgecenter/en/SSPLFC_7.2.0/UserGuide/c_cmdb_reconcilation_overview.html