具有两个不同键的实体的REST API URI

具有两个不同键的实体的REST API URI,rest,api,data-modeling,Rest,Api,Data Modeling,我必须设计一个API来管理一个文档实体:这个实体的原创性在于它可以有两个不同的ID: id1(编号,即1234) id2(编号,即89) 对于每个文档,只有一个id可用(id1或id2,不是两者都可用) 通常,我通过使用查询参数执行某种“搜索”功能来解决此问题: 但它只有在没有子实体的情况下才有效 比如说,我想找到文档的作者: GET /documents/1234/authors 不可能,因为我不知道我得到的是什么类型的id:是id1还是id2 GET /documents/author

我必须设计一个API来管理一个文档实体:这个实体的原创性在于它可以有两个不同的ID:

  • id1(编号,即1234)
  • id2(编号,即89)
对于每个文档,只有一个id可用(id1或id2,不是两者都可用)

通常,我通过使用查询参数执行某种“搜索”功能来解决此问题:

但它只有在没有子实体的情况下才有效

比如说,我想找到文档的作者:

GET /documents/1234/authors
不可能,因为我不知道我得到的是什么类型的id:是id1还是id2

GET /documents/authors?id1=1234
我认为不是真正的REST,因为id1指的是“作者”实体,而不是“文档”

GET /id1-documents/1234/authors
GET /id2-documents/1234/authors
然后创建两个URI,它们返回的是同一个实体(/author),但实际上并不符合REST

GET /documents/id1=1234/authors
GET /documents/id2=89/authors
它看起来像是只为API创建的复合键,没有“后端”的含义。对我来说,动态创建“复合”键听起来很奇怪

GET /document-authors?id1=1234
GET /document-authors?id2=89
在这种情况下,你完全失去了树的概念。。。最终的API只包含根实体

你看到另一种选择了吗? 哪一个看起来最好


非常感谢。

在我看来,您在这里把两种不同的资源混为一谈-
文档
作者
文档
作者
有关系,但它们应该是独立的资源,因为
作者
存在于任何单个文档中。考虑到这一点,您需要询问您的客户是否正在搜索作者或文档。如果是作者,那么他们应该查询作者API而不是文档API

e、 对于ID189、ID1234或ID2444文档的所有作者,您可以这样查询

GET/authors?docId1=89&docId1=1234&docId2=4444

这将返回作者表示的列表。如果人们关心文档本身,那么作者表示可以包含指向文档的链接

或者,如果您正在查找
文档
,那么您应该直接查询该文档

GET/documents?id1=89&id1=1234&id2=4444


作为子资源建模的内容实际上不是子资源。这是两个独立资源之间的关系,应该建模为一组链接。从
documents
api返回的每个文档都应该包含一组
作者
链接(如果人们真的关心作者),反之亦然,从作者到文档

这里有一个来自SlashDB的固执己见的解决方案,它允许同时过滤记录和遍历相关资源

该示例与您的类似-两个实体艺术家和唱片集

让我们先确定艺术家的身份

艺术家身份证:

艺术家姓名:

艺术家可能发行过专辑。这两个实体是相关的。我们允许使用相关实体的名称扩展URL,如下所示:

你可以继续“走”,比如说去看那些专辑里的曲目

甚至还可以继续过滤,即只过滤短于300000毫秒的曲目:


您能详细说明这两种不同类型的ID吗?在您的示例中,它们看起来都像int,那么这是否意味着您可以有两个id为“89”的不同文档,但一个文档具有id1 89,另一个文档具有id2 89?或者ID是否以某种方式正交/不重叠?谢谢您的评论。两个ID都是整数,没有限制。但如果定义了id1,那么id2就不是了,而且是相反的。是的,您可以有两个id为“89”的不同文档,但其中一个文档的id为189,另一个文档的id为289。问题在于细节。这样的URI看起来和感觉都很简单和自然,但是当您需要在筛选字段中的数据中考虑“/”时,实现会变得更加复杂。查询字符串方法在这方面更容易,但看起来不像imho那么干净。很抱歉,我不清楚哪个建议最适合您。谢谢你的回答。事实上,作者并不是一个真正的子资源,这是一个糟糕的例子。假设文档有一个子资源称为“签名”或“元数据”,那么它就是真正的子资源。我应该如何设计?谢谢,您只需要构造URI,使两种类型的标识符是不同的,例如
/documents/id1Type/89
/documents/id2Type/12345
。然后,每个文档都有一个唯一的URI,子资源位于定义良好的文档URI(
/documents/id1Type/89/signatures
)下。感谢您的回答。事实上,这可能是一个解决方案:我在stackoverflow上多次看到这种可能性。但是id1Type不是一个实体,不是一个真正的对象,这不是一个问题吗?如果我实现了这一点,我将得到两条路径:GET/documents/id2Type/{id}/signatures和GET/documents/id1Type/{id}/signatures。2个URI返回相同的资源,否?再次感谢根据您对id类型的描述,任何文档只能有一个id,这是两个id类型之一,但id重叠,因此您需要一种方法来区分它们。通过在允许返回文档的路径中命名id类型(如果该id存在),否则404-so URI语义是安全的。搜索应该转到顶级的
/documents
资源,这样就不会成为问题。另外,从概念上讲
/documents/idtype1
可以是一个资源-它可以返回该id类型的所有文档,也可以用于创建该id类型的文档。资源和实体不是一回事。谢谢你的回答。它看起来真的很像@sisyphus解决方案,所以我想如果很多人都同意这个解决方案,那肯定很有趣;)
GET /document-authors?id1=1234
GET /document-authors?id2=89