当前位置:  开发笔记 > 编程语言 > 正文

用于搜索的RESTful URL设计

如何解决《用于搜索的RESTfulURL设计》经验,为你挑选了7个好方法。

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

设置:我有两个模型,汽车和车库,汽车可以在车库.所以我的网址看起来像:

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

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

汽车可以独立存在(因此/汽车),也可以存在于车库中.例如,在给定车库中代表所有车辆的正确方法是什么?就像是:

/garage/yyy/cars     ?

车库yyy和zzz中的汽车联盟怎么样?

什么是代表搜索具有某些属性的汽车的正确方法?说:给我看看所有带4扇门的蓝色轿车:

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

或者它应该是/汽车而不是?

使用"搜索"似乎不合适 - 什么是更好的方式/术语?应该只是:

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

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

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

[更新]我喜欢贾斯汀的答案,但他没有涉及多字段搜索案例:

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

或类似的东西.我们怎么样

/cars/color/blue

到多场案件?



1> pbreitenbach..:

对于搜索,请使用查询字符串.这完全是RESTful:

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

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


这是对的.查询字符串的重点是执行搜索等操作.
那些你想要比较器(>,<,<=,> =)的情况呢?/车?评级<= 3?
确实这是正确的,因为根据[RFC3986](http://tools.ietf.org/html/rfc3986#section-3.4),路径_and_ querystring标识资源.更重要的是,正确的命名只是`/ cars?color = whatever`.
@mjs`/ cars?param = value`用于汽车列表上的简单**过滤**和`/ cars/search?param = value`用于创建**搜索**(没有持久性的ou)结果可能包含搜索评分,分类等.您还可以创建/删除命名搜索,如`/ cars/search/mysearch`.看看:http://stackoverflow.com/a/18933902/1480391
@YvesM.我很困惑,但我之前的评论在编辑之前提到了原始答案:http://stackoverflow.com/revisions/1081720/1.我同意你的观点,如果搜索是不同的东西,那么"搜索"出现在资源的名称中是有意义的.我不认为这是原始问题所要求的.
如果要访问嵌套在查询字符串下的资源,该怎么办?例如`/ cars?color = blue&type = sedan&doors = 4/engines`将无效

2> Qwerty..:

REST风格的漂亮的URL设计是用来显示基于结构的资源(类似目录的结构,日期:文章/ 2005/5/13,对象和它的属性,..),斜线/表示分层结构,使用-id来代替.

层次结构

我个人更喜欢:

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

如果用户删除了该/car-id部件,则会带来cars预览 - 直观.用户确切地知道他在树的哪个位置,他在看什么.他从第一眼看就知道,车库和汽车是有关系的./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   #I don't recommend using &*

或者基本上任何不是如上所述的斜线的东西.
公式:/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

可能的功能?

否定搜索字符串(!)
搜索任何汽车,但 搜索黑色红色:
?color=!black,!red
color:(!black,!red)

加入搜索
搜索红色蓝色黑色汽车行驶3门在车库编号1..20101..103999,但不是 5 /garage[id=1-20,101-103,999,!5]/cars[color=red,blue,black;doors=3]
然后,您可以构建更复杂的搜索查询.(查看CSS3属性匹配以获得匹配子串的想法.例如,搜索包含"bar"的用户user*=bar.)

结论

无论如何,这可能是你最重要的部分,因为你可以做但它像你毕竟只是记住,REST风格的 URI表示这是很容易理解,比如类似目录的结构/directory/file,/collection/node/item,枣/articles/{year}/{month}/{day}..当你忽略任何最后一段,你立即知道你得到了什么.

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

毫无保留: a-zA-Z0-9_.-~

版权所有: ;/?:@=&$-_.+!*'(),

不安全*: <>"#%{}|\^~[]`

*为什么不安全以及为什么要编码:RFC 1738见2.2

RFC 3986见2.2
尽管我之前曾说过,但这里有一个共同的区分,意思是某些""更重要.

通用分隔符: :/?#[]@

子定界符: !$&'()*+,;=

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


当查询字符串被充分理解和标准化时,为什么要构成非标准方案?
@Qwerty:很棒的帖子!我想知道:使用`;`而不是`&`的唯一原因是可读性?因为如果是这样,我想我实际上更喜欢`&`,因为它是更常见的分隔符......对吗?:) 谢谢!
我不相信我没想过在查询字符串中使用JSON.这是我遇到的问题的答案 - 复杂的搜索结构,而不使用`POST`.此外,您在答案中提出的其他想法也非常值得注意.非常感谢!
@Flo确实是:),但请记住,只有开发人员知道`&`作为分隔符.父母,祖父母和非受过教育的人口接受共同书面文本中使用的分隔符.

3> Doug Domeny..:

虽然在路径中具有参数具有一些优点,但IMO有一些超重因素.

并非URL中允许搜索查询所需的所有字符.大多数标点符号和Unicode字符都需要进行URL编码作为查询字符串参数.我正在努力解决同样的问题.我想在URL中使用XPath,但并非所有XPath语法都与URI路径兼容.因此,对于简单路径,/cars/doors/driver/lock/combination将适当的位置combination放在驱动程序门XML文档中.但/car/doors[id='driver' and lock/combination='1234']不是那么友好.

在根据其中一个属性过滤资源和指定资源之间存在差异.

例如,因为

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

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

要返回汽车,路径就是

/cars?color=red,blue,green 要么 /cars/search?color=red,blue,green

路径中的参数更难以读取,因为名称/值对不与路径的其余部分隔离,而不是名称/值对.

最后一条评论.我更喜欢/garages/yyy/cars(总是复数)/garage/yyy/cars(也许这是原始答案中的拼写错误),因为它避免改变单数和复数之间的路径.对于添加了's'的单词,改变并不是那么糟糕,但/person/yyy/friends改为/people/yyy看起来很麻烦.


是的,我同意...除了我的东西urls路径结构应该反映实体之间的自然关系,某种地图我的资源,像一个车库有很多车,一辆车属于一个车库等...并让过滤器参数,导致这就是我们所说的,查询查询...你怎么看?

4> Rich Apodaca..:

为了扩展彼得的答案 - 你可以使搜索成为一流的资源:

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或任何其他格式指定.与Car和Garage资源一样,您可以根据身份验证限制对搜索的访问.经常运行相同搜索的用户可以将其存储在其配置文件中,以便不需要重新创建它们.这些网址足够短,在很多情况下,它们可以通过电子邮件轻松交易.这些存储的搜索可以是自定义RSS源的基础,依此类推.

当您将搜索视为资源时,可以使用搜索.

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


这种方法不符合使用不安分协议的想法吗?我的意思是,坚持搜索到数据库是一种有状态的连接......不是吗?
这更像是有状态的服务.每次添加新车或车库时,我们也会改变服务状态.搜索只是可以与所有HTTP谓词一起使用的另一种资源.
REST与漂亮的URI或URI嵌套等无关.如果将URI定义为API的一部分,则不是REST.
以上如何定义URI约定?
我之前已经争论过这一点。这绝不是有状态的,但这是一件可怕的事情。搜索的“删除”不是很清楚,在这里您是说它删除了该搜索实体,但是我想使用它删除通过该搜索找到的结果。请不要将“搜索”添加为资源。

5> Peter Hilton..:

Justin的答案可能是要走的路,尽管在某些应用程序中将特定搜索本身视为资源可能是有意义的,例如,如果您想支持已命名的已保存搜索:

/search/{searchQuery}

要么

/search/{savedSearchName}


没有.将动作作为资源是没有意义的.

6> aehlke..:

这不是REST.您无法为API中的资源定义URI.资源导航必须是超文本驱动的.如果你想要漂亮的URI和大量的耦合,那就好了,但是不要把它称为REST,因为它直接违反了RESTful架构的约束.

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


你是正确的,它不是REST,它是RESTful系统的URL设计.但是,如果它违反了RESTful架构,那么你也是错误的.REST的超文本约束与RESTful系统的良好URL设计正交; 我记得几年前在Roy列表上与Roy T. Fielding进行了讨论,我参与了他明确表达的地方.换句话说,可以具有超文本和URL设计.RESTful系统的URL设计就像编程中的缩进; 不是必需的,但是一个非常好的主意(忽略Python等)
对不起,你说的没错.我刚刚从OP那里得到的印象是,他将让客户知道如何构建URL - 他会将URL"布局"作为他的API的一部分.*那*将违反REST.

7> user2108278..:

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

1)最简单的情况,查询相关元素和导航.

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

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

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

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

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

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有