我正在寻找一种合理的方法将搜索表示为RESTful url。

设置:我有两个模型,汽车和车库,汽车可以在车库。我的url是这样的:

/car/xxxx
  xxx == car id
  returns car with given id

/garage/yyy
  yyy = garage id
  returns garage with given id

Car可以独立存在(因此有/ Car),也可以存在于车库中。如何正确地表示给定车库中的所有汽车?喜欢的东西:

/garage/yyy/cars     ?

车库里的车yyy和zzz的组合呢?

用什么正确的方式来表示搜索具有特定属性的汽车?说:给我看所有四门的蓝色轿车。

/car/search?color=blue&type=sedan&doors=4

或者应该改为/cars ?

在这里使用“搜索”似乎不合适——还有什么更好的方式/术语吗?它应该是:

/cars/?color=blue&type=sedan&doors=4

搜索参数应该是PATHINFO或QUERYSTRING的一部分吗?

简而言之,我正在寻找跨模型REST url设计和搜索的指导。

[更新]我喜欢贾斯汀的答案,但他没有涵盖多领域搜索的情况:

/cars/color:blue/type:sedan/doors:4

或者类似的东西。我们如何从

/cars/color/blue

多域的情况?


当前回答

RESTful pretty URL设计是关于基于结构(类似目录的结构,日期:articles/2005/5/13,对象及其属性,..)显示资源,斜杠/表示层次结构,使用-id代替。

层次结构

我个人更喜欢:

/garage-id/cars/car-id
/cars/car-id   #for cars not in garages

如果用户删除了/car-id部分,它将带来直观的汽车预览。用户确切地知道他在树的什么位置,他在看什么。他一看就知道车库和汽车是有关系的。与/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   #also possible, but & blends in with text

或者基本上任何不是斜杠的东西,如上所述。 公式:/cars[?;]color[=-:]blue[,;+&],尽管我不会使用&符号,因为如果这是你的东西,第一眼从文本中无法识别。

**你知道在URI中传递JSON对象是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

可能的功能?

否定搜索字符串(!) 搜查所有车,但不包括黑车和红车 ?颜色=黑色!红色的 颜色:(黑色!红色)

加入搜索 在id 1的车库中搜索红色、蓝色或黑色的3门汽车。20或101..103或999,而不是5 /车库[id = 1 - 20101 - 103999, ! 5] /汽车[=红色、蓝色、黑色,门= 3) 然后可以构造更复杂的搜索查询。(查看CSS3属性匹配,了解匹配子字符串的思想。例如,搜索包含“bar”user*=bar的用户。)

结论

不管怎样,这对您来说可能是最重要的部分,因为您可以按照自己的想法来做,只要记住RESTful URI表示一个容易理解的结构,例如类似目录的/目录/文件、/集合/节点/项、日期/文章/{年}/{月}/{日}..当你省略最后的任何部分时,你马上就知道你得到了什么。

所以. .,所有这些字符都允许未编码:

无限制的:a-zA-Z0-9_. - ~ 通常允许编码和不允许,这两种用法是等效的。 特殊字符:$-_.+!*'(), 保留:;/ ?: @ = & 可以按照它们所代表的目的未编码地使用,否则必须对它们进行编码。 不安全的 : <>"#%{}|^~[]` 为什么不安全,为什么应该编码:RFC 1738见2.2

更多字符类请参见RFC 1738#page-20。

RFC 3986见2.2 尽管我之前说过,这里有一个常见的delimeter的区别,这意味着一些“比”其他更重要。

发电机:[] @ sub-delimeters : !$&'()*+,;=

更多阅读: 层次结构:见2.3,见1.2.3 Url路径参数语法 CSS3属性匹配 IBM: rest式Web服务——基础知识 注:RFC 1738由RFC 3986更新

其他回答

虽然我喜欢贾斯汀的回答,但我觉得它更准确地代表了一种过滤,而不是一种搜索。如果我想知道以小卡开头的车呢? 在我看来,你可以把它构建到你处理特定资源的方式中: /汽车/ cam * 或者,你可以简单地将它添加到过滤器中: /汽车/门/ 4 /名称/ cam * /颜色/红色、蓝色、绿色 就我个人而言,我更喜欢后者,但我绝不是REST方面的专家(我第一次听说REST只是在两周前左右……)

虽然在路径中设置参数有一些优势,但在我看来,还有一些重要因素。

Not all characters needed for a search query are permitted in a URL. Most punctuation and Unicode characters would need to be URL encoded as a query string parameter. I'm wrestling with the same problem. I would like to use XPath in the URL, but not all XPath syntax is compatible with a URI path. So for simple paths, /cars/doors/driver/lock/combination would be appropriate to locate the 'combination' element in the driver's door XML document. But /car/doors[id='driver' and lock/combination='1234'] is not so friendly. There is a difference between filtering a resource based on one of its attributes and specifying a resource. For example, since /cars/colors returns a list of all colors for all cars (the resource returned is a collection of color objects) /cars/colors/red,blue,green would return a list of color objects that are red, blue or green, not a collection of cars. To return cars, the path would be /cars?color=red,blue,green or /cars/search?color=red,blue,green Parameters in the path are more difficult to read because name/value pairs are not isolated from the rest of the path, which is not name/value pairs.

最后一个评论。我更喜欢/garages/yyy/cars(总是复数)而不是/garage/yyy/cars(也许这是原始答案中的一个拼写错误),因为它避免了在单数和复数之间改变路径。对于加了's'的单词,变化不是很糟糕,但将/person/yyy/friends改为/people/yyy似乎很麻烦。

扩展Peter的回答——你可以让搜索成为一流的资源:

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)

The Search resource would have fields for color, make model, garaged status, etc and could be specified in XML, JSON, or any other format. Like the Car and Garage resource, you could restrict access to Searches based on authentication. Users who frequently run the same Searches can store them in their profiles so that they don't need to be re-created. The URLs will be short enough that in many cases they can be easily traded via email. These stored Searches can be the basis of custom RSS feeds, and so on.

当您将搜索视为资源时,有许多使用搜索的可能性。

这个想法在Railscast中有更详细的解释。

对于搜索,使用querystrings。这是完美的RESTful:

/cars?color=blue&type=sedan&doors=4

常规查询字符串的一个优点是它们是标准的、被广泛理解的,并且它们可以从form-get生成。

Justin的答案可能是正确的,尽管在某些应用程序中,将特定的搜索视为其本身的资源可能是有意义的,比如如果你想支持命名保存的搜索:

/search/{searchQuery}

or

/search/{savedSearchName}