У меня есть конечная точка, которая может содержать большое количество ресурсов.Они возвращаются в нумерованном списке.Каждый ресурс имеет уникальное 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
}
]
Проблемы, с которыми я сталкиваюсь при таком подходе:
a) Использование индексов массива в path
в операциях исправления.Каждый ресурс уже имеет уникальный идентификатор.Я бы лучше использовал это.
б) Я не уверен, к чему должен относиться индекс массива в разбивке на страницы?Я предполагаю, что он должен ссылаться на глобальный индекс, как только все страницы будут получены и объединены друг с другом.
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
в операциях исправления.«Данные» в возвращаемых ресурсах больше не будут списком:
{
"pagination": {
"prevMarker": 123,
"nextMarker": 345
},
"data": {
"12": {
"id": 12,
"rank": 2,
"otherData": {}
},
"35": {
"id": 35,
"rank": 0,
"otherData": {}
},
"67": {
"id": 67,
"rank": 1,
"otherData": {}
}
}
}
Тогда я мог бы использовать уникальный идентификатор в операциях исправления.Например:
{
"op": "replace",
"path": "/data/12/rank",
"value": 0
}
Проблемы, с которыми я сталкиваюсь при таком подходе:
a) Коллекция my-resources может быть большой, у меня возникают трудности со значениемразбитого на страницы объекта json или разбитого на страницы словаря.Я не уверен, можно ли определить порядок итераций для этого большого объекта.
3) Иметь отдельную конечную точку для изменения рангов с помощью PUT
Мы могли бы добавить новую конечную точку, например, PUT /my-resource-ranks
.И ожидайте, что полный список заказанных идентификаторов будет передан в запросе PUT.Например,
[
{
"id": 12
},
{
"id": 35
},
{
"id": 67
}
]
Мы бы сделали поле MyResource.rank
только для чтения, чтобы его нельзя было изменить через другие конечные точки.
Проблемы, которые я вижу при таком подходе:
a) Необходимость отправить полный заказанный список.В запрос PUT для /my-resource-ranks
мы не будем включать никакие другие данные, а только уникальные идентификаторы ресурсов.Это менее серьезно, чем отправка полных ресурсов, но все же полный упорядоченный список может быть большим.
4) Избегайте поля MyResource.rank
, а "rank" будет порядком в ответе / my-collection.
В возвращенных ресурсах не будет поля "rank" иони будут уже отсортированы относительно их ранга в ответе.
{
"pagination": {
"prevMarker": 123,
"nextMarker": 345
},
"data": [
{
"id": 35,
"otherData": {}
},
{
"id": 67,
"otherData": {}
},
{
"id": 12,
"otherData": {}
}
]
}
Пользователь может изменить порядок с помощью операции move в json-patch.
[
{
"op": "test",
"path": "/data/2/id",
"value": 12
},
{
"op": "move",
"from": "/data/2",
"path": "/data/0"
}
]
Проблемы, которые я вижу при таком подходе:
a) Я бы предпочел, чтобы сервер мог вернуться к /my-collections
в «произвольном» порядке с точки зрения клиента.Пока порядок согласован, оптимальный порядок для «более простой» реализации сервера может отличаться от ранга, определенного приложением.
б) То же, что и 1) б).Указывает ли индекс в операции исправления на глобальный индекс после получения и объединения всех страниц друг с другом?Или это относится к индексу на текущей странице?
Обновление:
Кто-нибудь знает дополнительные примеры из существующего публичного API?Ищете дальнейшего вдохновения.Пока что у меня есть: