用于搜索资源的 RESTFul 平面层次结构与动态层次结构

Posted

技术标签:

【中文标题】用于搜索资源的 RESTFul 平面层次结构与动态层次结构【英文标题】:RESTFul Flat Hierarchy vs. Dynamic Hierarchy for Search Resource 【发布时间】:2014-11-10 10:09:23 【问题描述】:

我们正在创建一个 REST API,我们目前有两种方法来定义资源。

基本上我们有PatientsStudiesImages,其中PatientnStudiesStudyn@987654328 @。

分层方法

/webapi/patients/0/studies/12/images 

层次结构在 URI 中可见

要搜索所有图像,我们需要一个搜索资源

 /webapi/search?q=imageName:mountain

平面方法

/webapi/patients/0
/webapi/studies/12
/webapi/images/

层次结构由属性完成(例如,study 12patientId 为 0)。

要搜索所有图片,我们可以搜索资源本身:

 /webapi/images?q=imageName:mountain

是否有最佳实践方法或是否有人遇到过类似情况?是搜索资源 REST,还是在平面方法中看不到来自图像的关系是否很糟糕。

我们还需要考虑移动和修改。

【问题讨论】:

我认为两个 anweser 都会收到已解决的标志。所以我认为我的问题是放松。我希望这仍然可以帮助一些人。感谢 Aurélien 和 inf3mo。 另见***.com/questions/20951419/… 【参考方案1】:

平面和分层 URI 都可以是 RESTful。问题在别处。 RESTful 假设 URI 是 resourcesidentifiers

/wepapi/patients/0/studies/12/images 标识的是什么资源?研究的图像 12.

它真的是一个糟糕的标识符吗?不是真的。

会更好吗?绝对:

wepapi(获取资源表示的方式)与抽象资源无关。最 RESTful 的方法是为同一抽象资源的不同具体“表示”使用相同的 URI(有关详细信息,请参阅 HTTP Accept 标头)。 patients/0 不需要识别这些图像。您可能认为客户端软件通过解析 URI 来获取此数据会很酷,但是......他们不应该这样做。 URI 被称为“不透明”。

/search?q=imageName:mountain 标识的资源是什么?名为“山”的图像。

它真的是一个糟糕的标识符吗?并不真地。 会不会更好?绝对:

search 看起来像一个动词,应该会在 RESTful 设计者的头脑中引起很多警告。在某种程度上,我们可以说 URI 标识“搜索”或“搜索结果”(名词而不是动词),但认为它标识“图像”更安全。

最后但同样重要的是,在/studies/12/images/images/?studies=12 之间进行选择以便与/studies/12/images/?name=mountain 保持“一致”纯粹是一种软件设计选择。采用对您的应用程序更优雅的解决方案。它与 REST 无关,因为 URI 不应该被黑客入侵(请记住,它们应该是“不透明的”)。 URI 之间的链接是在它们的表示形式(JSON、XML、html...)中,而不是在它们的结构中。

【讨论】:

好主意。 :-) 我的意思是 SEARCH 真的应该是一个 HTTP 动词,其正文包含标准查询语言上的查询。像resources?q="URL serialized query"resources?reinvent=""&query=""&languages="" 这样的当前方法并不是那么好。【参考方案2】:

正如 Aurélien 指出的那样,设计 URI 结构不是 REST 问题。您应该遵循非常宽松的 URI 标准。例如,它声明路径是分层的,而查询是 URI 的非分层部分。 REST 的统一接口约束是关于使用标准解决方案,并且没有像 nice URI 这样的标准,所以从 REST 的角度来看,你如何构造你的 URI 并不重要,因为它们不会被客户端解析(除非您将 URI 模板用于模板目的)。

根据 HATEOAS 约束,您的客户端必须遵循服务发送的超链接。这些超链接必须用关于它们语义的元数据进行注释。该元数据可以是任何类型的链接数据。目前 IANA 链接关系是最典型的(通过非 RDF 格式),但您也可以使用 schema.org 操作等……(通过 RDF 格式)。所以客户端会检查链接的元数据,而不关心 URI 结构。

良好的 URI 结构仅对服务开发人员很重要。这很重要,因为有两件事:

它使路由更容易:如果 URI 可读,您可以更轻松地将端点映射到控制器。 您可以检查是否将 URI 映射到资源而不是操作。如果您无法清除 URI 中的每一个动词,那么就有问题了。例如,POST /users/123?update=true&partial=true body 不能删除 update。所以可能 HTTP 方法是错误的,因为动词去那里:PATCH /users/123 body 解决了问题。大多数动词都可以简化为标准 HTTP 方法,例如 GET, POST, PUT, DELETE, PATCH, etc...,因此实际上您(几乎)不需要新方法。

在我看来,扁平化方法更好,因为它更容易解析。通过查找东西,您通常依赖于单个 id,而不是多个 id。

/wepapi/patients/0/studies/12/images - 这是有道理的,因为您正在寻找来自第 0 位患者的第 12 次研究的图像。另一种方法是/images?patient=0&study=12,或者如果研究有唯一的 id,那么/images?study=0_12。顺便提一句。设计即席搜索查询并不是 REST 最详尽的部分。通过简单的查询,您可以使用 URI 的查询部分对其进行管理。

REST 不是您目前可以从实践中学习的东西。大多数人从不阅读或理解理论,所以那里有很多有缺陷的教程。您可能必须从Fielding dissertation 和一些其他论文开始,例如this one。有许多有趣且可能有用的项目仍在开发中,例如 Hydra、RESTdesc 等。因此,REST 实现远非一项精心设计的技术。我们可能还需要 15 年或更长时间......

【讨论】:

以上是关于用于搜索资源的 RESTFul 平面层次结构与动态层次结构的主要内容,如果未能解决你的问题,请参考以下文章

RESTful 介绍

RESTful

Restful风格接口书写规范

在数据仓库模型中容纳动态层次结构

在 RESTful 服务中处理多个资源请求

初始RESTful