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

多域的情况?


当前回答

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

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

其他回答

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

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

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

/search/{searchQuery}

or

/search/{savedSearchName}

对于你的情况,这里有很多好的选择。你仍然应该考虑使用POST主体。

查询字符串非常适合您的示例,但如果您有更复杂的东西,例如任意长的项目列表或布尔条件,您可能想要将post定义为一个文档,客户端通过post发送。

这允许更灵活的搜索描述,以及避免服务器URL长度限制。

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

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

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

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

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