2010-08-18 6 views
6

У меня есть REST API реализован в соответствии с принципом, что остальные просто возвращает основные документы и ссылки в этих документах Howto получить другие вещи, и т.д. и т.п.RESTful API сортировки дилемма

Например/автомобиль/5 даст мне модель: blabla, user_id: 1, а затем, если вам нужен владелец, вы получите/user/1, чтобы получить пользовательские данные.

Этот способ СОХРАНЕНИЯ и прочее избегают в БД .. все вещи связаны между собой и взаимосвязанными данными на клиентской части отдыха - хранение вещей прост легко кешировать/удалять кеш, масштаб и т. д.

Но что происходит, когда вам нужна сортировка?

Представьте, что у нас есть представление о интерфейсе для отображения следующих данных: Модель автомобиля, имя пользователя и т. Д. ... и вы хотите сортировать по имени пользователя, например.

Вы не можете действительно сказать/автомобиль/5 сортировать по имени пользователя потому что знает только пользовательских идентификаторов ...

Один из вариантов я вижу сортирует от пользователя/пользователя/список? SortBy = имя пользователя и затем соединение между этими возвращенными идентификаторами действительно относится к автомобилю. но это означает, что нам нужно получить ВСЕ пользователей ... и использовать только часть тех, которые кажутся узким местом убийцы.

Спасибо за любые указатели

ответ

5

Я думаю, что вы пытаетесь избежать присоединения по всем неправильным причинам, так как при таком подходе, вы будете иметь, чтобы обслуживать гораздо больше запросов.

Если вы вместо этого вернете всю информацию, которую вы бы указали (т. Е. Соединитесь с базой данных), то клиенты должны будут делать меньше запросов, а вы могли бы сделать свой выбор без необходимости (ленивый) загружает все дочерние объекты.

Другой вариант - вернуть дочерние объекты в виде дочерних элементов XML (аналогично тому, как работает интерфейс RESTful OpenStreetMap). У вас все еще есть один клик от клиента, и вы должны иметь возможность оптимизировать запросы, чтобы минимизировать нагрузку на БД.

4

Если вы избегаете всех подключений на сервере и оставляете его клиенту, тогда в этом случае вы также должны оставить сортировку клиенту. Это связано с тем, что для сортировки автомобилей по имени пользователя необходимо выполнить соединение.

Вы можете создать другой ресурс, называемый CarsAndOwners или аналогичный, который возвращает объединенный список, после чего становится разумным сортировать на сервере.

2

Я хотел бы начать, представляя идеальный RESTful запрос, который я хотел бы написать, например:

/car/list?sortby=username 

А затем выяснить, как осуществить это.

Теперь ваш список метод дает автомобиля объектов, которые не разоблачить имени как вы сказали, но я не думаю, что имеет значение. Вся сортировка должна выполняться на сервере до того, как будет подготовлен список.

Вы будете нуждаться, чтобы присоединиться к вашему автомобилю объектов пользователя объектов в каком-то момент для того, чтобы сделать это, и нет никакого способа уворачиваясь этого вопроса. Единственный выбор, который у вас есть, - это то, где вы это делаете.

Если вы работаете с традиционной РСУБД, имеет смысл сделать это на уровне БД.

Вы используете слой ORM между API приложения и базой данных?

+0

хорошо все сопротивление находится за REST .. в настоящее время отдых использует ORM, но я не думаю, что это актуально. –

+1

У меня есть намек на то, что вы использовали ORM, потому что вы сказали, что избегаете объединений в БД и соединяете все свои объекты на уровне приложения REST. Я вижу привлекательность этой простой чистой архитектуры, но это, вероятно, лежит в основе вашей текущей дилеммы. Я бы хотел скомпрометировать эту архитектуру, чтобы заставить приложение работать: наличие дополнительных хранимых процедур или представлений в БД, которые возвращают предварительно отсортированные данные, все еще обеспечивая сопоставление ORM для этих объектов и позволяя приложению REST между методами в зависимости от запроса. –

2

Прежде всего, ваш пример /car/5 должен быть множественную версию ресурса для того, чтобы быть RESTful:

/cars/5 
/users/1 

Теперь, в общем, если вы хотите RESTful подход к сортировке вы можете сделать это:

/cars?sort=make&order=asc 

В вашем примере вы указываете, что хотите сортировать автомобили по имени пользователя. Однако, как вы упомянули, коллекция cars ничего не должна знать о users. Итак, если вы хотите отобразить список автомобилей и сгруппировать их по пользователю, что вы будете делать? Вам нужен способ получить эту информацию. Один из способов сделать это является проходным пользователей и запрашивать машины, связанные с каждым пользователем:

# pseudo code 

users.each do |user| 
    # assuming the user id is 5, 
    # to display the user's cars, 
    # we need to request /users/5/cars 
end 

Таким образом, мы можем запросить список автомобилей для каждого человека в URL, как /users/5/cars. Это называется вложенным ресурсом. Мы запрашиваем только те автомобили, которые связаны с пользователем. 5.

Однако, у вас есть проблема с потенциально большим количеством запросов к вашему API (что может быть в порядке в зависимости от вашего варианта использования).

Другой подход, который, вероятно, лучше, чтобы сделать это в одном запросе на:

/users/cars?sort=username&order=asc 

будет возвращен массив пользователей и их автомобилей по заказу пользователя.

И еще один подход может быть:

/users?include=[cars]&sort=username&order=asc 

, но я не люблю этот подход, как много, как и предыдущий. Я бы рекомендовал предыдущий подход /users/cars.

Side Примечание: ваши списки должны быть пронумерованы так, чтобы не над головой запрашивающего все из users, когда вы только отображая частичный список.

/users?page=1&per_page=50 
+1

Множество имен ресурсов не является требованием REST. Требование - это единая семантика для разрешений для каждого ресурса: значение каждого открытого ресурса должно вести себя одинаково (с точки зрения потребителя) до доступных методов протокола (GET, POST , DELETE и т. Д.) –

1

Базы данных предназначены для быстрого соединения, поэтому его отказ от клиента или вашего серверного приложения для меня не имеет смысла.

Почти все, что я читал в REST, говорит о том, что отношения между сущностями/ресурсами также должны быть ресурсом. Поэтому у вас должен быть ресурс /mydomain.com/CarsAndUsers, который представляет это соединение/отношения.

Затем вы можете сделать сортировку по этому ресурсу так же, как и любой другой, и он будет обработан в базе данных:

/mydomain.com/CarsAndUsers?sortby=username

Вы также можете применить фильтрацию этот ресурс (и пейджинг), как и любой другой ресурс.

EDIT:

Согласно комментариям, было бы лучше сделать что-то вроде этого:?

/автомобили встраивать = пользователь, SortBy = имя пользователя

Спасибо Эрик за указание это из.

+0

Это рецепт комбинаторного взрыва конечных точек API. Более общий подход RESTful заключается в использовании параметров для запроса встроенных объектов (по существу, объединенных представлений). Например: '/ albums? Embed = artist'. Эти ресурсы, доступные для внедрения, могут иметь ссылки в коллекции гиперссылок 'links', чтобы сделать эту возможность доступной. –

+0

Спасибо Эрик, хотя я согласен с вашей точкой зрения о взрыве оконечных точек, вопрос заключается не в связанных объектах, а в сортировке одного набора на основе свойства связанного набора. Я не уверен, что вы предлагаете решить эту конкретную проблему. Или вы говорите, что OP может это сделать: /cars? Embed = пользователь, sortby = имя пользователя – rmcsharry

+0

Да, это в значительной степени то, что я предлагаю. –