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

Posted

技术标签:

【中文标题】如何通过 JSON API 实现复杂的条件批量部分更新?【英文标题】:How to implement complex conditional bulk partial updates via JSON API? 【发布时间】:2019-03-03 14:19:28 【问题描述】:

HTTP 协议中有POSTPATCH 方法用于部分更新。 在 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 解决方案不匹配,因为它们的 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"
    

【问题讨论】:

你确定这个架构不需要某种中间层(我想说数据库)来管理所有这些同时更新、权限检查等吗?我看不到您将如何审核这些更新,例如对于事件管理,首先。毫无疑问,我错过了一些重要的东西! 当然会有审计和数据库以及其余部分。问题是关于传输 JSON 数据格式,该格式将允许每个字段的不同源优先级。顺便说一句,我已经用来自属性优先级的想法的解决方案更新了原始问题。 【参考方案1】:

您需要某种优先级映射来决定每个客户端的优先级。

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

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

我找到了一份文档,可以澄清我的意思(它对某些 3rd 方工具有点具体,但概念就在那里):https://www.ibm.com/support/knowledgecenter/en/SSPLFC_7.2.0/UserGuide/c_cmdb_reconcilation_overview.html

【讨论】:

谢谢你,乍得。我检查了上述文档并根据属性优先级生成了一个解决方案。您可以在我更新的问题文本中看到它。

以上是关于如何通过 JSON API 实现复杂的条件批量部分更新?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过restful api传递部分对象(json)

oracle 如何实现对单个表批量更新

通过部分 json 更新 REST API

如何通过Dreamweaver批量对整个站点或目录进行代码搜索或部分全部替换

es批量删除文档json格式

Rest API - 部分更新