最初
RFC 3986§3.4(ユニフォームリソース識別子§(構文コンポーネント)|クエリ
3.4クエリ
クエリコンポーネントには、パスコンポーネント(セクション3.3)のデータとともに、URIのスキームおよび命名機関(ある場合)のスコープ内でリソースを識別するのに役立つ非階層データが含まれています。
クエリコンポーネントは、非階層データの取得用です。家系図よりも本質的に階層的なものはほとんどありません!Ergo- 「REST-y」であるかどうかに関係なく、インターネット上のシステムの開発、フォーマット、プロトコル、フレームワークに準拠するために、この情報を識別するためにクエリ文字列を使用しないでください。
RESTはこの定義とは関係ありません。
特定の質問に対処する前に、「検索」のクエリパラメータの名前が適切ではありません。より良いのは、クエリセグメントをキーと値のペアの辞書として扱うことです。
クエリ文字列は、より適切に定義できます
?first_name={firstName}&last_name={lastName}&birth_date={birthDate}
等
特定の質問に答える
1)どのAPI設計がよりRESTfulであり、その理由は何ですか?意味的には、同じ意味であり、同じように動作します。URIの最後のリソースは「子」であり、事実上、クライアントが子リソースを操作していることを意味します。
これは、あなたが信じているほど明確ではないと思います。
これらのリソースインターフェイスはRESTfulではありません。RESTfulアーキテクチャスタイルの主な前提条件は、アプリケーション状態の遷移をハイパーメディアとしてサーバーから伝達する必要があることです。人々はURIの構造を何とか「RESTful URI」にするために労力を費やしましたが、RESTに関する公式の文献には実際にはこれについてほとんど語ることができません。私個人の意見では、RESTに関するメタ誤情報の多くは、古くて悪い習慣を打破する目的で発行されたものです。(真に「RESTful」なシステムを構築するのは、実際にはかなり手間がかかります。業界は「REST」に夢中になり、無意味な資格と制限でいくつかの直交的な懸念を埋めました。
RESTの文献には、アプリケーションプロトコルとしてHTTPを使用する場合、プロトコルの仕様の正式な要件を遵守する必要があり、「httpを作成しながら、httpを使用していることを宣言する」ことはできないと書かれています。 ; リソースを識別するためにURIを使用する場合は、URI / URLに関する仕様の正式な要件に従う必要があります。
あなたの質問は、RFC3986§3.4で直接対処されています。この問題の一番下の行は、APIを「RESTful」と見なすにはURIが不十分であるにもかかわらず、システムを実際に「RESTful」にしたい場合、HTTPとURIを使用している場合、クエリ文字列:
3.4クエリ
クエリコンポーネントに非階層データが含まれています
...それは簡単です。
2)クライアントの観点からの理解可能性、およびデザイナーの観点からの保守性という点で、それぞれの長所と短所は何ですか。
最初の2つの「長所」は、正しい道にいるということです。3番目の「短所」は、完全に間違っているように見えることです。
理解可能性と保守性に関する限り、これらは間違いなく主観的であり、クライアント開発者の理解レベルと設計者の設計チョップに依存します。URI仕様は、URIのフォーマット方法に関する決定的な答えです。階層データは、パス上およびパスパラメーターで表されることになっています。非階層データはクエリで表現されることになっています。このセマンティクスは、要求されている表現のメディアタイプに特に依存するため、フラグメントはより複雑です。したがって、あなたの質問の「理解しやすい」コンポーネントに対処するために、最初の2つのURIが実際に言っていることを正確に翻訳しようとします。次に、有効なURIで達成しようとしているとあなたが言うことを表現しようとします。
逐語的なURIの意味的意味への翻訳
/myservice/api/v1/grandparents/{grandparentID}/parents/children?search={text}
これは、祖父母の両親search={text}
にとって、祖父母の兄弟を検索する場合にのみ、あなたのURIであなたが言ったことを首尾一貫している子供を見つけます。「祖父母、両親、子供」と「祖父母」が親に世代を上げ、そして親の子供を見ることによって「祖父母」世代に戻ったことを見つけた。
/myservice/api/v1/parents/{parentID}/children?search={text}
これは、{parentID}で識別される親について、?search={text}
これが望んでいるものに近い方の子を見つけ、API全体をモデル化するために使用できる親->子の関係を表していることを示しています。このようにモデル化するために、クライアントに「grandparentId」がある場合、所有するIDと表示したいファミリーグラフの部分の間に間接層があることを認識する負担がかかります。「grandparentId」で「子」を見つけるには、/parents/{parentID}/children
サービスを呼び出し、返された子をforeachして、子を検索して個人識別子を取得します。
URIとしての要件の実装
ツリーをたどることができる、より拡張可能なリソース識別子をモデル化する場合、それを実現するいくつかの方法が考えられます。
1)最初のものは、すでに言及しました。「人」のグラフを複合構造として表します。各人は、その親のパスを介してその上の世代への参照を持ち、その子のパスを介してその下の世代を参照します。
/Persons/Joe/Parents/Mother/Parents
ジョーの母方の祖父母をつかむ方法です。
/Persons/Joe/Parents/Parents
ジョーの祖父母のすべてをつかむ方法です。
/Persons/Joe/Parents/Parents?id={Joe.GrandparentID}
あなたが持っている識別子を持つジョーの祖父母をつかむでしょう。
これらはすべて理にかなっています(「Parents / Parents / Parents」パターンのブランチIDがないため、サーバーでdfsを強制することでタスクに応じてパフォーマンスが低下する可能性があることに注意してください)。任意の世代の世代をサポートする機能。何らかの理由で8世代を検索したい場合、これを次のように表すことができます。
/Persons/Joe/Parents/Parents/Parents/Parents/Parents/Parents/Parents/Parents?id={Joe.NotableAncestor}
しかし、これにより、このデータを表すための2番目の主要なオプション、つまりパスパラメーターが使用されます。
2)パスパラメータを使用して「階層を照会」する次の構造を開発して、消費者の負担を軽減し、なおかつ意味のあるAPIを使用できます。
147世代を振り返って、このリソース識別子をパスパラメーターで表すと、次のことが可能になります。
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor}
JoeをGreat Grandparentから見つけるには、Joe's Idの既知の世代数をグラフで確認します。
/Persons/JoesGreatGrandparent/Children;generations=3?id={Joe.Id}
これらのアプローチで注目すべき重要な点は、識別子とリクエストにさらなる情報がなければ、最初のURIがJoe.NotableAncestorの識別子でJoeから147世代後のPersonを取得していることを期待することです。2番目のものがJoeを取得することを期待する必要があります。実際に必要なのは、呼び出し元のクライアントがノードのセット全体と、ルートPersonとURIの最終コンテキストとの関係を取得できることです。同じURI(装飾を追加)text/vnd.graphviz
でこれを実行し、リクエストでAcceptを設定できます。これは、.dot
グラフ表現のIANA登録メディアタイプです。それで、URIを
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor.Id}#directed
HTTPリクエストヘッダー
Accept: text/vnd.graphviz
を使用すると、147番目の先祖世代にJoeの「注目すべき祖先」として識別される人物が含まれる場合、Joeと147世代の間の世代階層の有向グラフが必要であることをクライアントにかなり明確に伝えることができます。
text / vnd.graphvizがそのフラグメントに対して事前定義されたセマンティクスを持っているかどうかはわかりません。命令の検索で何も見つかりませんでした。そのメディアタイプに実際に事前定義されたフラグメント情報がある場合は、そのセマンティクスに従って、準拠するURIを作成する必要があります。ただし、これらのセマンティクスが事前に定義されていない場合、URI仕様では、フラグメント識別子のセマンティクスは制約を受けず、代わりにサーバーによって定義されるため、この使用法は有効です。
3)リソースの「フィルタリング」以外に、実際に使用されるクエリ文字列は何ですか?最初の方法を使用する場合、フィルターパラメーターは、クエリ文字列パラメーターではなく、パスパラメーターとしてURI自体に埋め込まれます。
私はすでにこれを徹底的に打ち負かしたと思いますが、クエリ文字列はリソースを「フィルタリング」するためのものではありません。これらは、非階層データからリソースを識別するためのものです。あなたが行くことによって、あなたのパスを指定して、階層をドリルダウンしている場合は
/person/{id}/children/
、あなたが識別するために希望されている特定の子供や、特定の子供のセットを、あなたが識別し、クエリ内に含まれているセットに適用されるいくつかの属性を使用します。