Как реализовать RESTful API для изменения порядка в больших записях коллекции? - PullRequest
0 голосов
/ 31 января 2019

У меня есть конечная точка, которая может содержать большое количество ресурсов.Они возвращаются в нумерованном списке.Каждый ресурс имеет уникальное 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?Ищете дальнейшего вдохновения.Пока что у меня есть:

1 Ответ

0 голосов
/ 31 января 2019

Я бы

  • Использовать PATCH
  • Определить специальный тип контента специально для обновления заказа.

Тип application / patch + jsonотлично подходит для прямых модификаций, но я думаю, что ваш сценарий использования достаточно уникален, чтобы гарантировать полезный минимальный специализированный тип контента.

...