如何为大型集合条目上的订单更改实现RESTful API?

时间:2019-01-31 00:52:43

标签: rest api http json-patch

我的端点可能包含大量个资源。它们以分页列表形式返回。每个资源都有一个唯一的id,一个rank字段和一些其他数据。 在语义上,资源是根据其rank进行排序的。用户应该能够更改该顺序。我正在寻找一个RESTful接口来更改大型集合中许多资源中的rank字段。

对一种资源进行重新排序可能会导致许多资源的rank字段发生变化。例如,考虑将最不重要的资源移到最重要的位置。许多资源可能需要“降级”。

正在分页的集合使问题更加棘手。之前有一个similar question关于一个小收藏夹

rank字段是整数类型。如果可以提供合理的界面,则可以更改其类型。


例如:

GET /my-resources?limit=3&marker=234返回:

{
  "pagination": {
    "prevMarker": 123,
    "nextMarker": 345
  },
  "data": [
    {
      "id": 12,
      "rank": 2,
      "otherData": {}
    },
    {
      "id": 35,
      "rank": 0,
      "otherData": {}
    },
    {
      "id": 67,
      "rank": 1,
      "otherData": {}
    }
  ]
}

考虑的方法。

1)对列表的PATCH请求。

我们可以使用标准的json-patch请求修改等级字段。例如以下内容:

[
  {
    "op": "replace",
    "path": "/data/0/rank",
    "value": 0
  },
  {
    "op": "replace",
    "path": "/data/1/rank",
    "value": 1
  },
  {
    "op": "replace",
    "path": "/data/2/rank",
    "value": 2
  }
]

这种方法遇到的问题:

a)在补丁操作中使用path中的数组索引。每个资源已经具有唯一的ID。我宁愿使用它。

b)我不确定在分页集合中应该引用什么数组索引?我想一旦接收到所有页面并背靠背合并,它应该引用全局索引。

c)集合中资源的索引可能会被其他客户端更改。当前客户在索引1上的想法可能不再在该索引上。我想可以先在补丁请求中添加测试操作。因此完整的补丁程序请求应如下所示:

[
  {
    "op": "test",
    "path": "/data/0/id",
    "value": 12
  },
  {
    "op": "test",
    "path": "/data/1/id",
    "value": 35
  },
  {
    "op": "test",
    "path": "/data/2/id",
    "value": 67
  },
  {
    "op": "replace",
    "path": "/data/0/rank",
    "value": 0
  },
  {
    "op": "replace",
    "path": "/data/1/rank",
    "value": 1
  },
  {
    "op": "replace",
    "path": "/data/2/rank",
    "value": 2
  }
]

2)将集合设为“字典” / json对象,并使用补丁程序请求字典。

此方法优于1)的优点是,我们可以在补丁操作中使用path中的唯一ID。 返回的资源中的“数据”将不再是列表:

{
  "pagination": {
    "prevMarker": 123,
    "nextMarker": 345
  },
  "data": {
    "12": {
      "id": 12,
      "rank": 2,
      "otherData": {}
    },
    "35": {
      "id": 35,
      "rank": 0,
      "otherData": {}
    },
    "67": {
      "id": 67,
      "rank": 1,
      "otherData": {}
    }
  }
}

然后,我可以在补丁操作中使用唯一的ID。例如:

{
    "op": "replace",
    "path": "/data/12/rank",
    "value": 0
  }

这种方法遇到的问题:

a)my-resources集合可能很大,我对分页的json对象或分页的字典的含义有疑问。我不确定是否可以在这个大对象上定义迭代顺序。

3)有一个单独的端点,用于通过PUT修改等级

我们可以添加一个新的端点,例如PUT /my-resource-ranks。 并期望在PUT请求中传递订购ID的完整列表。例如

[
  {
    "id": 12
  },
  {
    "id": 35
  },
  {
    "id": 67
  }
]

我们会将MyResource.rank设置为readOnly字段,以便无法通过其他端点进行修改。

这种方法遇到的问题:

a)需要发送完整的订购清单。在/my-resource-ranks的PUT请求中,我们将不包括任何其他数据,而仅包括资源的唯一ID。它没有发送完整资源那么严重,但是完整的有序列表仍然很大。

4)避免将MyResource.rank字段和“ rank”作为/ my-collections响应中的顺序。

返回的资源中将没有“ rank”字段,并且已经根据响应中的排名对其进行了排序。

{
  "pagination": {
    "prevMarker": 123,
    "nextMarker": 345
  },
  "data": [
    {
      "id": 35,
      "otherData": {}
    },
    {
      "id": 67,
      "otherData": {}
    },
    {
      "id": 12,
      "otherData": {}
    }
  ]
}

用户可以使用json-patch中的move操作来更改顺序。

[
  {
    "op": "test",
    "path": "/data/2/id",
    "value": 12
  },
  {
    "op": "move",
    "from": "/data/2",
    "path": "/data/0"
  }
]

这种方法遇到的问题:

a)从客户端的角度来看,我希望服务器可以按“任意”顺序返回到/my-collections的自由。只要顺序是一致的,“简单”服务器实现的最佳顺序可能与应用程序定义的等级不同。

b)与1)b)相同。一旦收到所有页面并将它们背靠背合并,补丁操作中的索引是否会引用全局索引?还是引用当前页面中的索引?


更新:

有人知道来自现有公共API的更多示例吗?寻找更多灵感。到目前为止,我有:

1 个答案:

答案 0 :(得分:0)

我会

  • 使用PATCH
  • 定义专门用于更新订单的特殊内容类型。

application / patch + json类型非常适合进行直接修改,但是我认为您的用例非常独特,足以保证有用,最少的专业内容类型。