用于过滤的多个资源上的 RESTful API 多个查询字符串
Posted
技术标签:
【中文标题】用于过滤的多个资源上的 RESTful API 多个查询字符串【英文标题】:RESTful API Multiple Query Strings over multiple Resources for Filtering 【发布时间】:2018-02-05 16:18:54 【问题描述】:假设有一个实体公司和一个实体国家。一个公司可以属于多个国家,一个国家可以有多个公司。因此,对于公司来说,有一个具有不同角色的中间表成员资格,例如一家公司是一个国家的制造商,而另一家公司是一个国家的供应商。一个国家可以有多种状态,例如 is_active 等。
现在我们要从角色为制造商且国家状态为 is_active = false 的特定公司获取所有国家/地区。
RESTful API 端点如何查找此用例?是否允许过滤多个资源?一些想法:
GET /companies/id/nations?role=manufacturer&is_active=false
GET /memberships/id/nations?role=manufacturer&is_active=false
更新 也许我的问题不够清楚。查询字符串参数在两个不同的表/实体中进行查找。角色在成员资格实体内,而 is_active 在国家实体内。我认为只允许对请求的资源进行过滤。也许我可以把这个问题分成两个用例。
1) 使用 URI 中的中间资源是否“更好”? 2) 我们可以在多个表/实体上过滤带有查询字符串参数的资源吗?
【问题讨论】:
这完全取决于您作为 API 设计器如何实现它。 REST 不关心 URI 的外观,因为 URI 的语义是在关系本身中提供的。 【参考方案1】:REST 不在乎您对标识符使用什么拼写。任何编码到 URI 中的数据都由服务器自行决定并供其使用。
这基本上意味着只要您的 URI 符合 RFC 3986,您就做对了。这意味着:
Hierarchical data 属于路径 - 允许通用客户端以正确的方式解析相对引用。非分层数据属于查询。
是否允许过滤多个资源?
其他方式 - 标识符与可能从多行数据加载/过滤状态的单个资源匹配。
GET /companies/id/nations?role=manufacturer&is_active=false
GET /companies/id/nations?role=manufacturer&is_active=true
这是两个不同的资源;它们恰好由相同的参数化查询支持这一事实是一个实现细节。
查询字符串参数在两个不同的表/实体中进行查找。
这是一个实现细节。就 API 使用者而言,您可能只是从键值存储中提取准备好的文档。
这是重点的一部分——即使底层实现需要更改,API 也应该是稳定的。将集成接口与当前数据模式紧密耦合会使向后兼容的更改更加困难。
我认为只允许对请求的资源进行过滤。
没有。就 REST 而言,整个 URI 是一个标识符。客户端使用该 URI 来访问和操作资源。对于资源的实现在接口后面的样子,绝对没有 REST 约束。它可以是文档存储、单个表、许多表、第 3 方服务,以及所有这些的某种组合......
您用来提供当前表示的服务器端框架可能会关心 - 某些标识符比其他标识符更适合您的路由策略,该框架可能会将您限制为数据需要存储在一个地方的约定.但这些都只是实现细节。 REST 不在乎。
我们可以在多个表/实体上过滤带有查询字符串参数的资源吗?
“过滤资源”的拼写并不完全正确,因为它会将您的集成资源(REST 关心的东西)与您的数据模型混淆。
能否从存储在多个表中的数据创建单个资源的表示?当然。是否可以将资源限制为来自那些满足某些过滤规范的表中的数据?当然。对哪些过滤器可以应用于哪些表有任何限制吗?没有。
吉姆·韦伯:
URI 不映射到域对象 - 这违反了封装...。您应该期望集成域中的资源比业务域中的业务对象多得多。
【讨论】:
@DehMotth ad 1) 关于 URI 内部的逻辑没有对错之分,因此这个问题相当基于意见。广告 2) 是什么阻止您这样做?您还可以查看矩阵参数,您可以在其中直接在相应段上指定参数,而不是在末尾附加它们。不过,由于您已经指定了一个具体的 ID,我不确定在这种特殊情况下进一步过滤机制的有用性【参考方案2】:这是一个在 SlashDB 中实现的固执己见的答案。
考虑一下这种情况,它与您的情况非常相似:
曲目 -- 播放列表
一个曲目可以位于多个播放列表中,一个播放列表通常由许多曲目组成。下面的 URL 是可点击的,并将显示资源的 html 表示:
这里是播放列表“古典”的 URI:
https://demo.slashdb.com/db/Chinook/Playlist/Name/Classical
现在,让我们转到传递表 PlaylistTrack
https://demo.slashdb.com/db/Chinook/Playlist/Name/Classical/PlaylistTrack
由于 PlaylistTrack 与 Track 有关系,我们可以将其添加为最后一段:
https://demo.slashdb.com/db/Chinook/Playlist/Name/Classical/PlaylistTrack/Track
您可以选择遵循相同的模式。当一般实现时,它将允许对您的数据模型进行非常惊人的过滤和遍历。
例如,让我们在古典播放列表中查找曲目的发票,但只查找来自法国、奥地利或意大利的曲目,以及总金额在 3 到 10 美元之间的曲目。
https://demo.slashdb.com/db/Chinook/Playlist/Name/Classical/PlaylistTrack/Track/InvoiceLine/Invoice/BillingCountry/France,Austria,Italy/Total/3..10
【讨论】:
以上是关于用于过滤的多个资源上的 RESTful API 多个查询字符串的主要内容,如果未能解决你的问题,请参考以下文章