我正在寻找一种合理的方法将搜索表示为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

多域的情况?


当前回答

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

其他回答

RESTful不建议在URL的/cars/search中使用动词。过滤/搜索/分页API的正确方法是通过查询参数。然而,在某些情况下,你不得不打破常规。例如,如果您正在跨多个资源进行搜索,那么您必须使用类似/search?q =查询

您可以访问http://saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices/了解设计RESTful API的最佳实践

我使用两种方法来实现搜索。

1)最简单的情况,用于查询相关元素,并用于导航。

    /cars?q.garage.id.eq=1

这意味着,查询车库ID等于1的汽车。

也可以创建更复杂的搜索:

    /cars?q.garage.street.eq=FirstStreet&q.color.ne=red&offset=300&max=100

FirstStreet所有车库中不是红色的汽车(第三页,每页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

此外,我还建议:

/cars/search/all{?color,model,year}
/cars/search/by-parameters{?color,model,year}
/cars/search/by-vendor{?vendor}

这里,Search被认为是Cars资源的子资源。

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

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似乎很麻烦。

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