用于搜索的RESTful URL设计

用于搜索的RESTful URL设计,rest,Rest,我正在寻找一种合理的方法,将搜索表示为RESTful URL 设置:我有两个模型,汽车和车库,汽车可以在车库里。所以我的URL看起来像: /car/xxxx xxx == car id returns car with given id /garage/yyy yyy = garage id returns garage with given id 汽车可以独立存在(因此为/Car),也可以存在于车库中。比如说,代表某个车库中所有汽车的正确方式是什么?比如: /garage/

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

设置:我有两个模型,汽车和车库,汽车可以在车库里。所以我的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怎么样

搜索具有特定属性的汽车的正确方式是什么?说:让我看看所有四门蓝色轿车:

/car/search?color=blue&type=sedan&doors=4
还是应该换成汽车

使用“搜索”似乎不合适——有什么更好的方法/术语?应该是:

/cars/?color=blue&type=sedan&doors=4
搜索参数应该是PATHINFO或QUERYSTRING的一部分吗

简而言之,我正在寻找关于跨模型RESTURL设计和搜索的指导

[更新]我喜欢Justin的回答,但他没有涵盖多字段搜索案例:

/cars/color:blue/type:sedan/doors:4
或者类似的。我们从何而来

/cars/color/blue

对于多字段情况?

我的建议是:

/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 :) )
编辑:

希望这能给你一个想法。本质上,您的RESTAPI应该易于发现,并使您能够浏览数据。使用URL而不是查询字符串的另一个优点是,您可以利用web服务器上存在的用于HTTP流量的本机缓存机制

下面是一个页面链接,该页面描述了REST中查询字符串的弊端:

我使用谷歌的缓存是因为普通页面对我不起作用,这里还有一个链接:
贾斯廷的答案可能是走的路,尽管在一些应用程序中,将特定搜索视为自己的资源是有意义的,例如,如果您想支持命名的保存搜索:

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


虽然我喜欢贾斯汀的回答,但我觉得它更准确地代表了一个过滤器而不是一个搜索。如果我想知道名字以cam开头的汽车怎么办?

在我看来,您可以将其构建为处理特定资源的方式:
/汽车/凸轮*

或者,您可以简单地将其添加到过滤器中:
/汽车/门/4/名称/凸轮*/颜色/红、蓝、绿


就个人而言,我更喜欢后者,但我绝对不是REST方面的专家(在大约两周前才第一次听说过它…

虽然在路径中使用参数有一些优势,但在我看来,有一些重要因素

  • URL中不允许搜索查询所需的所有字符。大多数标点符号和Unicode字符都需要URL编码为查询字符串参数。我正在努力解决同样的问题。我希望在URL中使用XPath,但并非所有XPath语法都与URI路径兼容。因此,对于简单路径,
    /cars/doors/driver/lock/composition
    适合在驾驶员车门XML文档中定位“
    composition
    ”元素。但是
    /car/doors[id='driver'和lock/composition='1234']
    并不友好

  • 根据资源的一个属性筛选资源与指定资源之间存在差异

    比如说,

    /cars/colors
    返回所有汽车的所有颜色列表(返回的资源是颜色对象的集合)

    /cars/colors/red、blue、green
    将返回红色、蓝色或绿色的颜色对象列表,而不是汽车集合

    要归还汽车,路径将是

    /cars?color=红、蓝、绿
    /cars/search?color=红、蓝、绿

  • 路径中的参数更难读取,因为名称/值对与路径的其余部分(不是名称/值对)没有隔离


最后一点意见。我更喜欢
/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)
搜索资源将具有颜色、制作模型、车库状态等字段,并且可以用XML、JSON或任何其他格式指定。与汽车和车库资源一样,您可以基于身份验证限制对搜索的访问。经常运行相同搜索的用户可以将它们存储在他们的配置文件中,这样就不需要重新创建它们。URL将足够短,在许多情况下,它们可以通过电子邮件轻松交易。这些存储的搜索可以作为定制RSS提要的基础,等等

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


这篇文章更详细地解释了这个想法。

对于搜索,请使用querystring。这是非常安静的:

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

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

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


REST的发明者看到了这一点。

RESTful漂亮的URL设计是关于基于结构(类似目录的结构,日期:articles/2005/5/13,object及其属性,…)显示资源,斜杠
/
表示层次结构,请改用
-id

层次结构 我个人更喜欢:

/garage id/cars/car id
/汽车/汽车id#适用于不在车库内的汽车
如果用户删除了
/car id
部分,则会带来
车辆
预览-直观。用户确切知道
/cars?color=blue&type=sedan&doors=4
    /cars?q.garage.id.eq=1
    /cars?q.garage.street.eq=FirstStreet&q.color.ne=red&offset=300&max=100
    POST /searches  => Create
    GET  /searches/1  => Recover search
    GET  /searches/1?offset=300&max=100  => pagination in search
    {  
       "$class":"test.Car",
       "$q":{
          "$eq" : { "color" : "red" },
          "garage" : {
             "$ne" : { "street" : "FirstStreet" }
          }
       }
    }
/cars/search/all{?color,model,year}
/cars/search/by-parameters{?color,model,year}
/cars/search/by-vendor{?vendor}