2010-08-18 13 views
6

Ich habe REST API nach dem Prinzip implementiert, die nur Ruhe die Grundlagen und Refs in diesen Dokumenten gibt zurück HowTo andere Dinge etc etcRESTful API Sortierung Dilemma

Zum Beispiel a/Auto/5 gibt mir Modell: blabla, user_id: 1 und dann, wenn Sie den Besitzer benötigen, erhalten Sie/user/1, um Benutzerdaten zu erhalten.

Auf diese Weise JOINS und Sachen sind in DB vermieden .. alle Dinge sind Verknüpfung zwischen sich selbst und Daten miteinander verbunden auf Rest-Client-Teil - Dinge einfach zu halten Cache/Drop-Cache, Maßstab etc.

Aber was passiert, wenn Sie sortieren müssen?

Stellen Sie sich vor, wir haben eine Ansicht auf dem Frontend, um folgende Daten anzuzeigen: Automodell, Benutzername, etc ... und Sie möchten nach Benutzernamen zum Beispiel sortieren.

Man kann nicht wirklich das sagen/Auto/5 nach Usernamen zu sortieren weil es nur von Benutzer-IDs weiß ...

Eine Option, die ich sehe, ist das Sortieren von Benutzern/user/list? Sortby = Benutzername und dann verbinden, welche der zurückgegebenen IDs sich tatsächlich auf das Auto beziehen. aber das bedeutet, wir müssen alle Benutzer .. und nur einen Bruchteil von denen, die Killer Leistung Engpass scheint.

Danke für alle Hinweise

Antwort

5

Ich glaube, Sie versuchen, aus den falschen Gründen zu vermeiden Beitritt, wie sie durch diesen Ansatz, Sie gehen viel mehr Anfragen haben zu warten.

Wenn Sie stattdessen alle Informationen zurückholen, die Sie anzeigen würden (zB die Seite der Joins-Datenbank), müssen die Clients weniger Abfragen durchführen, und Sie können Ihre Sortierung durchführen, ohne dass Sie (faul) lädt alle untergeordneten Objekte.

Die andere Option wäre, die untergeordneten Objekte als untergeordnete XML-Elemente zurückzubringen (ähnlich wie die RESTful-Schnittstelle von OpenStreetMap funktioniert). Sie haben immer noch einen einzigen Treffer vom Client, und Sie sollten in der Lage sein, die Abfragen zu optimieren, um die Belastung der Datenbank zu minimieren.

4

Wenn Sie alle Joins auf dem Server vermeiden und sie dem Client überlassen, müssen Sie in diesem Fall die Sortierung ebenfalls dem Client überlassen. Dies liegt daran, dass ein Join stattfinden muss, um die Autos nach Usern zu sortieren.

Sie können eine andere Ressource namens CarsAndOwners oder ähnliches erstellen, die die verknüpfte Liste zurückgibt. An diesem Punkt wird es sinnvoll, auf dem Server zu sortieren.

2

ich durch die Vorstellung, die ideale RESTful Abfrage starten würde, Ich mag würde schreiben, zum Beispiel:

/car/list?sortby=username 

Und dann herauszufinden, wie das realisieren.

Jetzt ist Ihre Liste Methode gibt Ihnen Auto Objekte, die Benutzername wie Sie gesagt nicht aussetzen, aber ich glaube nicht, dass Angelegenheiten. Die gesamte Sortierung sollte auf dem Server stattfinden, bevor die Liste vorbereitet wird.

Sie gehen zu müssen, Ihr Auto Objekte Benutzer Objekte an einem gewissen Punkt verbinden, um dies zu tun, und es gibt keine Möglichkeit, diese Frage auszuweichen. Die einzige Wahl, die Sie haben, ist, wo Sie es tun.

Wenn Sie mit einem traditionellen RDBMS arbeiten, ist es sinnvoll, dies auf DB-Ebene zu tun.


Verwenden Sie eine ORM-Schicht zwischen Ihrer Anwendungs-API und der Datenbank?

+0

gut alle persistance ist hinter dem REST..zurück derzeit ist ORM verwenden, aber ich denke nicht, dass dies relevant ist. –

+1

Ich habe den Hinweis erhalten, dass Sie ORM verwendet haben, weil Sie gesagt haben, dass Sie Joins in der DB vermieden haben und alle Ihre Objekte in der REST-Anwendungsebene verbunden haben. Ich kann die Attraktivität dieser einfachen sauberen Architektur sehen, aber es ist wahrscheinlich die Wurzel Ihres aktuellen Dilemmas. Ich würde versuchen, diese Architektur zu kompromittieren, um die Anwendung zum Laufen zu bringen: zusätzliche gespeicherte Prozeduren oder Ansichten auf der Datenbank, die die Daten vorsortiert zurückgeben, ORM-Mapping für diese Objekte bereitstellen und die REST-Anwendung auswählen lassen zwischen Methoden abhängig von der Abfrage. –

2

Zunächst einmal Ihr Beispiel /car/5 sollte die Mehrzahl Version der Ressource sein, um RESTful sein:

/cars/5 
/users/1 

nun im Allgemeinen, wenn Sie einen RESTful Ansatz zur Sortierung möchten, können Sie dies tun:

/cars?sort=make&order=asc 

In Ihrem Beispiel erwähnen Sie, dass Sie Autos nach Benutzernamen sortieren möchten. Wie Sie jedoch erwähnen, sollte die cars Sammlung nichts über users wissen. Also, wenn Sie eine Liste von Autos anzeigen und sie nach Benutzer gruppieren möchten, was tun Sie? Sie benötigen eine Möglichkeit, diese Informationen abzurufen. Eine Möglichkeit, dies zu tun, ist eine Schleife durch die Benutzer und fordern die Autos jedem Benutzer zugeordnet:

# 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 

So können wir die Liste der Autos für jeden einzelnen an einer URL wie /users/5/cars anfordern. Dies wird als verschachtelte Ressource bezeichnet. Wir fragen nur die Autos an, die mit Benutzer 5 in Verbindung stehen.

Sie haben jedoch das Problem, viele Anfragen an Ihre API zu stellen (was in Abhängigkeit von Ihrem Anwendungsfall in Ordnung sein kann).

Ein weiterer Ansatz, die wahrscheinlich besser ist, ist dies in einer Anfrage zu tun: nach Benutzername Dies würde einen Array von Benutzern und ihre Autos

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

.

Und doch könnte einen anderen Ansatz:

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

aber ich nicht so viel wie die vorherigen, wie dieser Ansatz. Ich würde den vorherigen Ansatz von /users/cars empfehlen.

Randbemerkung: Ihre Listen sollten paginiert werden, so dass es nicht der Aufwand ist fordern alle des users, wenn Sie nur eine Teilliste angezeigt werden.

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

Die mehrfache Ressourcennamensgebung ist keine Voraussetzung für REST - was eine Voraussetzung ist, ist eine einheitliche Semantik für Affordanzen für jede Ressource: Jede exponierte Ressource sollte sich aus der Perspektive des Konsumenten genauso verhalten wie die verfügbaren Protokollmethoden (GET, POST) , DELETE, etc ...) –

1

Datenbanken sind so konzipiert, Joins schnell zu tun, so dass es für den Client oder Ihre Server-Anwendung macht keinen Sinn für mich.

Fast alles, was ich in REST gelesen habe, besagt, dass Beziehungen zwischen Entitäten/Ressourcen auch eine Ressource sein sollten. Daher sollten Sie eine Ressource /mydomain.com/CarsAndUsers haben, die diese Verknüpfung/Beziehung darstellt.

Dann können Sie auf diese Ressource Sortierung tun wie jeder andere, und es wird von der Datenbank behandelt werden:

/mydomain.com/CarsAndUsers?sortby=username

Sie können auch Filterung gelten diese Ressource (und Paging) genau wie jede andere Ressource.

EDIT:

sich nach den Kommentaren wäre es besser, so etwas zu tun:

/Autos einbetten = user, sortby = username

Dank Eric für den Hinweis das heraus.

+0

Das ist ein Rezept für die kombinatorische Explosion von API-Endpunkten. Ein üblicherer REST-Ansatz besteht darin, Parameter zu verwenden, um inline-Objekte (im Wesentlichen verbundene Repräsentationen) anzufordern. Zum Beispiel: '/ albums? Embed = artist'. Die für die Einbettung verfügbaren Ressourcen können Links in einer hypermedia "links" -Sammlung enthalten, um die Option erkennbar zu machen. –

+0

Dank Eric, während ich mit Ihrem Punkt über die Explosion von Endpunkten einverstanden bin, geht es nicht um verwandte Objekte, sondern darum, einen Satz basierend auf der Eigenschaft einer verwandten Menge zu sortieren. Ich bin nicht sicher, was Sie vorschlagen, löst dieses spezielle Problem. Oder sagst du, dass das OP das tun könnte: /autos? Embed = user, sortby = username – rmcsharry

+0

Ja, das ist ziemlich genau das, was ich vorschlage. –