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

多域的情况?


当前回答

扩展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中有更详细的解释。

其他回答

我的建议是:

/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而不是查询字符串的另一个优点是,您可以利用web服务器上存在的用于HTTP流量的本机缓存机制。

这里有一个页面链接,该页面描述了REST中查询字符串的害处:http://web.archive.org/web/20070815111413/http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful

我使用谷歌的缓存,因为正常的页面不为我工作,这里的链接以及: http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful

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

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的最佳实践

这不是REST。您不能为API内的资源定义uri。资源导航必须是超文本驱动的。如果您想要漂亮的uri和大量的耦合,这是可以的,但是不要将其称为REST,因为它直接违反了RESTful体系结构的约束。

请参阅REST发明者的这篇文章。

扩展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中有更详细的解释。