質問
検索をRESTful URLとして表す合理的な方法を探しています。
セットアップ:車とガレージの2つのモデルがあり、車をガレージに入れることができます。だから私のURLは次のようになります:
/car/xxxx
xxx == car id
returns car with given id
/garage/yyy
yyy = garage id
returns garage with given id
車は、単独で存在することができるため(/ car)、またはガレージに存在することができます。たとえば、指定されたガレージ内のすべての車を表す正しい方法は何ですか?次のようなもの:
/garage/yyy/cars ?
ガレージyyyとzzzの車の組合はどうですか?
特定の属性を持つ車の検索を表す正しい方法は何ですか?説明:4ドアの青いセダンをすべて見せてください:
/car/search?color=blue&type=sedan&doors=4
または代わりに/ carsにする必要がありますか?
" search"の使用そこでは不適切と思われる-より良い方法/用語は何ですか?ただあるべきです:
/cars/?color=blue&type=sedan&doors=4
検索パラメーターはPATHINFOまたはQUERYSTRINGの一部ですか?
要するに、クロスモデルのREST URLデザインと検索のガイダンスを探しています。
[更新]ジャスティンの答えは好きですが、彼はマルチフィールド検索のケースをカバーしていません。
/cars/color:blue/type:sedan/doors:4
またはそのようなもの。どうやって行くの
/cars/color/blue
複数フィールドの場合
解決
検索には、クエリ文字列を使用します。これは完全にRESTfulです:
/cars?color=blue&type=sedan&doors=4
通常のクエリ文字列の利点は、標準で広く理解されており、form-getから生成できることです。
他のヒント
RESTfulプリティURLデザインは、構造(ディレクトリのような構造、日付:articles / 2005/5/13、オブジェクトとその属性など)に基づいてリソースを表示することです。スラッシュ /
は階層構造を示し、代わりに -id
を使用します。
階層構造
私は個人的に好みます:
/garage-id/cars/car-id
/cars/car-id #for cars not in garages
ユーザーが / car-id
部分を削除すると、直感的に cars
プレビューが表示されます。ユーザーは、ツリーのどこにいるのか、何を見ているのかを正確に知っています。彼は最初の外観から、ガレージと車が関係していることを知っています。 / car-id
は、 / car / id
とは異なり、一緒に属していることも示します。
検索中
検索クエリはそのままで問題ありません、あなたの好みだけが考慮されます。検索に参加するときに面白い部分があります(以下を参照)。
/cars?color=blue;type=sedan #most prefered by me
/cars;color-blue+doors-4+type-sedan #looks good when using car-id
/cars?color=blue&doors=4&type=sedan #I don't recommend using &*
または基本的には、上記で説明したようなスラッシュではないもの。
式: / cars [?;] color [=-:] blue [、; +&]
、* &
記号を使用しませんが一見するとテキストから認識できません。
** JSONオブジェクトをURIで渡すことはRESTfulであることをご存知ですか? **
オプションのリスト
/cars?color=black,blue,red;doors=3,5;type=sedan #most prefered by me
/cars?color:black:blue:red;doors:3:5;type:sedan
/cars?color(black,blue,red);doors(3,5);type(sedan) #does not look bad at all
/cars?color:(black,blue,red);doors:(3,5);type:sedan #little difference
可能な機能?
検索文字列の否定(!)
車を検索するが、ではない 黒および赤:
?color =!black、!red
color :(!black、!red)
参加検索
ガレージID 1..20 に 3 ドアがある red または blue または black の車を検索しますem>または 101..103 または 999 がではない 5
/ garage [id = 1-20,101-103,999、!5] / cars [color = red、blue、black; doors = 3]
その後、より複雑な検索クエリを作成できます。 ( CSS3属性の一致を見て、部分文字列の一致のアイデアを見つけてください。たとえば、&quotを含むユーザーの検索; bar" user * = bar
)
結論
とにかく、これはあなたにとって最も重要な部分かもしれません。なぜなら、あなたが好きなようにできるからです。 RESTful URIは、たとえばディレクトリのような / directory / file
、 / collection / node / item
、日付 / articles / {year} / {month} / {day}
..そして、最後のセグメントのいずれかを省略すると、何が得られるかすぐにわかります。
したがって、これらのすべての文字は、エンコードされないことが許可されています:
- 未予約:
a-zA-Z0-9 _.-〜
- 予約済み:
; /?:@ =& $ -_。+!* '()、
- 安全でない*:
<>"#%{} | \ ^〜[] `
*安全ではない理由とエンコードする必要がある理由: RFC 1738 2.2を参照
RFC 3986 2.2を参照
以前に言ったことにも関わらず、ここにデリミターの一般的な区別があります。つまり、一部の"" は他のものよりも重要です。
- 汎用デリミター:
:/?#[] @
- サブデリメーター:
!$& '()* +、; =
その他の読み物:
階層: 2.3を参照、 1.2.3を参照
URLパスパラメーターの構文
CSS3属性の一致
IBM:RESTful Webサービス-basi
パスにパラメーターがあることにはいくつかの利点がありますが、IMOにはいくつかの重要な要素があります。
-
検索クエリに必要なすべての文字がURLで許可されているわけではありません。ほとんどの句読点とUnicode文字は、クエリ文字列パラメーターとしてURLエンコードする必要があります。私は同じ問題に取り組んでいます。 URLでXPathを使用したいのですが、すべてのXPath構文がURIパスと互換性があるわけではありません。したがって、単純なパスの場合、ドライバーのドアXMLドキュメントで「
combination
」要素を見つけるには、/ cars / doors / driver / lock / combination
が適切です。しかし、/ car / doors [id = 'driver'およびlock / combination = '1234']
はそれほどフレンドリーではありません。 -
属性の1つに基づいてリソースをフィルタリングすることと、リソースを指定することには違いがあります。
たとえば、
/ cars / colors
は、すべての車のすべての色のリストを返します(返されるリソースは色オブジェクトのコレクションです)/ cars / colors / red、blue、green
は、車のコレクションではなく、赤、青、または緑の色オブジェクトのリストを返します。車を返すには、パスは次のようになります
/ cars?color = red、blue、green
または/ cars / search?color = red、blue、green
-
名前/値のペアはパスの残りの部分(名前/値のペアではない)から分離されていないため、パスのパラメーターは読みにくくなります。
最後のコメント。 / garage / yyy / cars
(常に複数形)よりも / garage / yyy / cars
(おそらく元の回答のタイプミスだった)を好む単数形と複数形の間。 「s」が追加された単語の場合、変更はそれほど悪くありませんが、 / person / yyy / friends
を / people / yyy
に変更するのは面倒です。
Peterの答えを拡張するには、Searchを一流のリソースにすることができます。
POST /searches # create a new search
GET /searches # list all searches (admin)
GET /searches/{id} # show the results of a previously-run search
DELETE /searches/{id} # delete a search (admin)
検索リソースには、色、モデルの作成、ガレージステータスなどのフィールドがあり、XML、JSON、またはその他の形式で指定できます。 Car and Garageリソースのように、認証に基づいて検索へのアクセスを制限できます。同じ検索を頻繁に実行するユーザーは、プロファイルにそれらを保存できるため、再作成する必要はありません。 URLは十分に短いため、多くの場合、メールで簡単に取引できます。これらの保存された検索は、カスタムRSSフィードなどの基礎になります。
検索をリソースと考えると、検索を使用する多くの可能性があります。
アイデアは、この Railscast で詳細に説明されています。
>Justinの答えはおそらく進むべき道です。ただし、アプリケーションによっては、特定の検索を、名前付き保存検索をサポートする場合など、それ自体がリソースとして考えるのが理にかなっている場合があります。
/search/{searchQuery}
または
/search/{savedSearchName}
これはRESTではありません。 API内のリソースのURIを定義することはできません。リソースナビゲーションはハイパーテキスト駆動である必要があります。きれいなURIと大量のカップリングが必要な場合は問題ありませんが、RESTfulアーキテクチャの制約に直接違反するため、RESTとは呼ばないでください。
発明者による記事をご覧くださいRESTの。
検索を実装するには、2つのアプローチを使用します。
1)最も単純なケース、関連する要素のクエリ、およびナビゲーション。
/cars?q.garage.id.eq=1
これは、ガレージIDが1の車を照会することを意味します。
より複雑な検索を作成することもできます:
/cars?q.garage.street.eq=FirstStreet&q.color.ne=red&offset=300&max=100
FirstStreetのすべてのガレージにある車のうち、赤ではない車(3ページ目、ページあたり100要素)。
2)複雑なクエリは、作成されて回復可能な通常のリソースと見なされます。
POST /searches => Create
GET /searches/1 => Recover search
GET /searches/1?offset=300&max=100 => pagination in search
検索作成のPOST本文は次のとおりです。
{
"$class":"test.Car",
"$q":{
"$eq" : { "color" : "red" },
"garage" : {
"$ne" : { "street" : "FirstStreet" }
}
}
}
Grails(基準DSL)に基づいています: http: //grails.org/doc/2.4.3/ref/Domain%20Classes/createCriteria.html
Justinの応答は気に入っていますが、検索よりもフィルターをより正確に表していると感じています。 camで始まる名前の車について知りたい場合はどうすればよいですか?
私の見方では、特定のリソースを処理する方法に組み込むことができます。
/ cars / cam *
または、単にフィルターに追加することもできます。
/ cars / doors / 4 / name / cam * / colors / red、blue、green
個人的には後者を好むが、私は決してRESTの専門家ではない(2週間ほど前に初めて聞いたことがある...)
RESTfulは、URLの/ cars / searchで動詞を使用することをお勧めしません。 APIをフィルタリング/検索/ページ分割する正しい方法は、クエリパラメータを使用することです。ただし、規範を破る必要がある場合があります。たとえば、複数のリソースを検索する場合は、/ search?q = query
のようなものを使用する必要がありますhttp://saipraveenblog.wordpress .com / 2014/09/29 / rest-api-best-practices / RESTful APIを設計するためのベストプラクティスを理解する
さらに、私もお勧めします:
/cars/search/all{?color,model,year}
/cars/search/by-parameters{?color,model,year}
/cars/search/by-vendor{?vendor}
ここでは、 Search
は Cars
リソースの子リソースと見なされます。
ここには、あなたのケースに適したオプションがたくさんあります。それでも、POST本体の使用を検討する必要があります。
クエリ文字列は例に最適ですが、もっと複雑なものがある場合、たとえばアイテムまたはブール条件の任意の長いリスト、クライアントがPOSTを介して送信するドキュメントとして投稿を定義することができます。
これにより、検索のより柔軟な説明が可能になり、サーバーURLの長さ制限が回避されます。
私のアドバイスはこれでしょう:
/garages
Returns list of garages (think JSON array here)
/garages/yyy
Returns specific garage
/garage/yyy/cars
Returns list of cars in garage
/garages/cars
Returns list of all cars in all garages (may not be practical of course)
/cars
Returns list of all cars
/cars/xxx
Returns specific car
/cars/colors
Returns lists of all posible colors for cars
/cars/colors/red,blue,green
Returns list of cars of the specific colors (yes commas are allowed :) )
編集:
/cars/colors/red,blue,green/doors/2
Returns list of all red,blue, and green cars with 2 doors.
/cars/type/hatchback,coupe/colors/red,blue,green/
Same idea as the above but a lil more intuitive.
/cars/colors/red,blue,green/doors/two-door,four-door
All cars that are red, blue, green and have either two or four doors.
うまくいけば、アイデアが得られます。基本的に、Rest APIは簡単に検出でき、データを参照できる必要があります。クエリ文字列ではなくURLを使用することのもう1つの利点は、Webサーバー上に存在するネイティブのキャッシュメカニズムをHTTPトラフィック用に利用できることです。
RESTのクエリ文字列の悪について説明するページへのリンク: http://web.archive.org/web/20070815111413/http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
通常のページが機能していなかったため、Googleのキャッシュを使用しました。ここにもそのリンクがあります。 http://rest.blueoxen.net/cgi-bin/wiki.pl? QueryStringsConsideredHarmful