我有一个可能包含大量资源的端点。它们以分页列表的形式返回。每个资源都有一个唯一的id
、一个rank
字段和一些其他数据。从语义上讲,资源是根据它们的rank
. 用户应该能够更改该顺序。我正在寻找一个 RESTful 接口来更改rank
大型集合中许多资源中的字段。
重新排序一个资源可能会导致rank
许多资源的字段发生变化。例如,考虑将最不重要的资源移动到最重要的位置。许多资源可能需要“降级”。
被分页的集合使问题变得更加棘手。之前也有过类似的问题,关于一个小合集
该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
}
]
我用这种方法看到的问题:
path
a)在补丁操作中使用数组索引。每个资源已经有一个唯一的 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
一个只读字段,因此它不能通过其他端点进行修改。
我用这种方法看到的问题:
a) 需要发送完整的有序列表。在 PUT 请求中,/my-resource-ranks
我们不会包含任何其他数据,而只会包含资源的唯一 ID。它没有发送完整资源那么严重,但完整的有序列表仍然可能很大。
4)避免MyResource.rank
字段和“排名”是 /my-collections 响应中的顺序。
返回的资源中不会包含“rank”字段,并且它们已经根据它们在响应中的排名进行了排序。
{
"pagination": {
"prevMarker": 123,
"nextMarker": 345
},
"data": [
{
"id": 35,
"otherData": {}
},
{
"id": 67,
"otherData": {}
},
{
"id": 12,
"otherData": {}
}
]
}
用户可以通过json-patch 中 的移动操作更改排序。
[
{
"op": "test",
"path": "/data/2/id",
"value": 12
},
{
"op": "move",
"from": "/data/2",
"path": "/data/0"
}
]
我用这种方法看到的问题:
/my-collections
a)从客户端的角度来看,我希望服务器可以自由地以“任意”顺序返回。只要顺序一致,“更简单”的服务器实现的最佳顺序可能与应用程序定义的等级不同。
b) 与 1)b) 相同的问题。一旦所有页面都被接收并背靠背合并,补丁操作中的索引是否引用全局索引?还是指当前页面中的索引?
更新:
有人知道现有公共 API 的更多示例吗?寻找进一步的灵感。到目前为止,我有: