Zuerst
Wie Per RFC 3986 § 3.4 (Uniform Resource Identifiers § (Syntax - Komponenten) | Abfrage
3.4 Abfrage
Die Abfragekomponente enthält nicht hierarchische Daten, die zusammen mit den Daten in der Pfadkomponente (Abschnitt 3.3) dazu dienen, eine Ressource im Rahmen des Schemas und der Benennungsberechtigung des URI (falls vorhanden) zu identifizieren.
Abfragekomponenten dienen zum Abrufen nicht hierarchischer Daten. Es gibt nur wenige Dinge, die hierarchischer sind als ein Stammbaum! Ergo - unabhängig davon, ob Sie es für "REST-y" halten oder nicht - um den Formaten, Protokollen und Frameworks von und für die Entwicklung von Systemen im Internet zu entsprechen, dürfen Sie diese Informationen nicht anhand der Abfragezeichenfolge identifizieren.
REST hat mit dieser Definition nichts zu tun.
Vor der Beantwortung Ihrer spezifischen Fragen ist Ihr Abfrageparameter "search" schlecht benannt. Besser wäre es, Ihr Abfragesegment als ein Wörterbuch von Schlüssel-Wert-Paaren zu behandeln.
Ihre Abfragezeichenfolge könnte besser definiert werden als
?first_name={firstName}&last_name={lastName}&birth_date={birthDate}
usw.
Um Ihre spezifischen Fragen zu beantworten
1) Welches API-Design ist restvoller und warum? Sie meinen und verhalten sich semantisch gleich. Die letzte Ressource in der URI ist "untergeordnete Ressource". Dies bedeutet, dass der Client die untergeordnete Ressource verarbeitet.
Ich denke nicht, dass dies so eindeutig ist, wie Sie zu glauben scheinen.
Keine dieser Ressourcenschnittstellen ist REST-konform. Die Hauptvoraussetzung für die RESTful Architektur ist , dass Anwendungszustandsübergänge vom Server als hypermedia mitgeteilt werden müssen. Die Leute haben über die Struktur von URIs nachgedacht, um sie irgendwie zu "RESTful URIs" zu machen, aber die formale Literatur zu REST hat dazu eigentlich sehr wenig zu sagen. Meiner persönlichen Meinung nach wurde ein Großteil der Meta-Fehlinformationen zu REST veröffentlicht, um alte, schlechte Gewohnheiten zu brechen. (Ein wirklich "RESTful" -System aufzubauen ist eigentlich ein ziemlicher Arbeitsaufwand. Die Branche hat sich auf "REST" beschränkt und einige orthogonale Bedenken mit unsinnigen Qualifikationen und Einschränkungen hinterfragt.)
In der REST-Literatur heißt es, dass Sie, wenn Sie HTTP als Anwendungsprotokoll verwenden möchten, die formalen Anforderungen der Protokollspezifikationen einhalten müssen und nicht "http auf dem Laufenden halten und immer noch deklarieren können, dass Sie http verwenden". ; Wenn Sie URIs zur Identifizierung Ihrer Ressourcen verwenden, müssen Sie die formalen Anforderungen der Spezifikationen bezüglich URI / URLs einhalten.
Ihre Frage wird direkt in RFC3986 §3.4 angesprochen, das ich oben verlinkt habe. Unterm Strich in dieser Sache ist , dass , obwohl eine konforme URI ist unzureichend , um eine API „RESTful“ zu betrachten, wenn Sie Ihr System wirklich wollen , sein „RESTful“ und Sie sind mit HTTP und URIs, dann können Sie nicht hierarchischen Daten durch die Identifizierung Abfragezeichenfolge, weil:
3.4 Abfrage
Die Abfragekomponente enthält nicht hierarchische Daten
...So einfach ist das.
2) Was sind die Vor- und Nachteile in Bezug auf die Verständlichkeit aus Sicht des Kunden und die Wartbarkeit aus Sicht des Designers?
Die "Profis" der ersten beiden sind, dass sie auf dem richtigen Weg sind . Das "Gegenteil" des dritten ist, dass es völlig falsch zu sein scheint.
Soweit es Ihre Verständlichkeit und Wartbarkeit betrifft, sind diese definitiv subjektiv und hängen vom Verständnisniveau des Kundenentwicklers und den Designchips des Designers ab. Die URI-Spezifikation ist die endgültige Antwort darauf, wie URIs formatiert werden sollen. Hierarchische Daten sollen auf dem Pfad und mit Pfadparametern dargestellt werden. Nicht hierarchische Daten sollen in der Abfrage dargestellt werden. Das Fragment ist komplizierter, da seine Semantik speziell vom Medientyp der angeforderten Darstellung abhängt. Um die "Verständlichkeit" -Komponente Ihrer Frage anzusprechen, werde ich versuchen, genau zu übersetzen, was Ihre ersten beiden URIs tatsächlich sagen. Dann versuche ich darzustellen, was Sie mit gültigen URIs erreichen wollen.
Übersetzung Ihrer wörtlichen URIs in ihre semantische Bedeutung
/myservice/api/v1/grandparents/{grandparentID}/parents/children?search={text}
Dies besagt, dass die Eltern von Großeltern feststellen, dass ihr Kind das hat, search={text}
was Sie mit Ihrer URI gesagt haben, nur dann schlüssig ist, wenn Sie nach den Geschwistern eines Großelternteils suchen. Mit Ihren "Großeltern, Eltern, Kindern" haben Sie herausgefunden, dass ein "Großelternteil" eine Generation zu ihren Eltern aufgestiegen ist und dann zu der "Großeltern" -Generation zurückgekehrt ist, indem Sie sich die Kinder der Eltern angesehen haben.
/myservice/api/v1/parents/{parentID}/children?search={text}
Dies besagt, dass für die Eltern, die durch {parentID} identifiziert wurden, das Kind gefunden werden muss. ?search={text}
Dies entspricht eher Ihren Vorstellungen und stellt eine Eltern-> Kind-Beziehung dar, die wahrscheinlich zum Modellieren Ihrer gesamten API verwendet werden kann. Um es auf diese Weise zu modellieren, muss der Kunde erkennen, dass, wenn er eine "grandparentId" hat, eine Indirektionsebene zwischen seiner ID und dem Teil des Familiendiagramms besteht, den er sehen möchte. Um ein "Kind" von "grandparentId" zu finden, können Sie Ihren /parents/{parentID}/children
Dienst anrufen und dann für jedes zurückgegebene Kind dessen Kinder nach Ihrer Personenkennung durchsuchen.
Implementierung Ihrer Anforderungen als URIs
Wenn Sie eine erweiterbarere Ressourcenkennung modellieren möchten, die den Baum durchsuchen kann, können Sie dies auf verschiedene Arten erreichen.
1) Den ersten habe ich schon angedeutet. Stellen Sie das Diagramm "People" als zusammengesetzte Struktur dar. Jede Person hat einen Verweis auf die Generation über ihr über ihren Elternpfad und auf eine Generation unter ihr über ihren Kinderpfad.
/Persons/Joe/Parents/Mother/Parents
wäre eine Möglichkeit, Joes Großeltern mütterlicherseits zu schnappen.
/Persons/Joe/Parents/Parents
wäre eine Möglichkeit, alle Großeltern von Joe zu schnappen.
/Persons/Joe/Parents/Parents?id={Joe.GrandparentID}
Ich würde Joes Großeltern mit der Kennung, die Sie in der Hand haben, packen.
und all dies wäre sinnvoll (beachten Sie, dass es hier je nach Aufgabe zu Leistungseinbußen kommen kann, wenn auf dem Server ein dfs erzwungen wird, da im Muster "Eltern / Eltern / Eltern" keine Zweigidentifikation vorhanden ist.) Sie profitieren auch von die Fähigkeit, eine beliebige Anzahl von Generationen zu unterstützen. Wenn Sie aus irgendeinem Grund 8 Generationen nachschlagen möchten, können Sie dies so darstellen
/Persons/Joe/Parents/Parents/Parents/Parents/Parents/Parents/Parents/Parents?id={Joe.NotableAncestor}
Dies führt jedoch zur zweiten dominanten Option für die Darstellung dieser Daten: über einen Pfadparameter.
2) Verwenden Sie Pfadparameter, um "die Hierarchie abzufragen". Sie könnten die folgende Struktur entwickeln, um die Belastung der Verbraucher zu verringern und dennoch eine sinnvolle API zu haben.
Um einen Blick auf 147 Generationen zu werfen, können Sie diesen Ressourcenbezeichner mit Pfadparametern darstellen
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor}
Um Joe von seinem Urgroßelternteil ausfindig zu machen, können Sie in der Grafik eine bekannte Anzahl von Generationen nach Joe's Id durchsuchen.
/Persons/JoesGreatGrandparent/Children;generations=3?id={Joe.Id}
Das Wichtigste bei diesen Ansätzen ist, dass Sie ohne weitere Informationen im Bezeichner und in der Anforderung erwarten sollten, dass der erste URI eine Person 147 Generationen von Joe mit dem Bezeichner Joe.NotableAncestor abruft. Sie sollten damit rechnen, dass der zweite Joe abruft. Angenommen, Sie möchten, dass Ihr aufrufender Client die gesamte Gruppe von Knoten und ihre Beziehungen zwischen der Stammperson und dem endgültigen Kontext Ihrer URI abrufen kann. Sie können dies mit demselben URI (mit einer zusätzlichen Dekoration) tun und text/vnd.graphviz
auf Ihre Anforderung hin ein Akzeptieren von festlegen, bei dem es sich um den von der IANA registrierten Medientyp für die .dot
Diagrammdarstellung handelt. Ändern Sie damit den URI in
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor.Id}#directed
Wenn Accept: text/vnd.graphviz
Sie einen HTTP-Anforderungsheader verwenden
, können Sie Kunden ziemlich klar mitteilen lassen, dass sie den gerichteten Graphen der Generationshierarchie zwischen Joe und 147 Generationen vor der 147. Ahnengeneration haben möchten, die eine Person enthält, die als Joes "Bemerkenswerter Vorfahre" identifiziert wurde.
Ich bin mir nicht sicher, ob text / vnd.graphviz eine vordefinierte Semantik für das Fragment hat, bei der Suche nach Anweisungen konnte ich keine finden. Wenn dieser Medientyp tatsächlich vordefinierte Fragmentinformationen enthält, sollte seine Semantik befolgt werden, um eine konforme URI zu erstellen. Wenn diese Semantik jedoch nicht vordefiniert ist, gibt die URI-Spezifikation an, dass die Semantik des Fragmentbezeichners nicht eingeschränkt und stattdessen vom Server definiert ist, wodurch diese Verwendung gültig wird.
3) Wofür werden Abfragezeichenfolgen wirklich verwendet, abgesehen vom "Filtern" Ihrer Ressource? Wenn Sie den ersten Ansatz wählen, wird der Filterparameter als Pfadparameter anstelle eines Abfragezeichenfolgenparameters in den URI selbst eingebettet.
Ich glaube, ich habe dies bereits gründlich zu Tode geprügelt, aber Abfragezeichenfolgen dienen nicht zum "Filtern" von Ressourcen. Sie dienen zur Identifizierung Ihrer Ressource anhand nicht hierarchischer Daten. Wenn Sie Ihre Hierarchie mit Ihrem Pfad aufgeschlüsselt haben
/person/{id}/children/
und ein bestimmtes Kind oder eine bestimmte Gruppe von Kindern identifizieren möchten , verwenden Sie ein Attribut, das für die Gruppe gilt, die Sie identifizieren, und fügen Sie es in die Abfrage ein.