Rest 标签应该是it';是自己的资源还是嵌套属性?

Rest 标签应该是it';是自己的资源还是嵌套属性?,rest,tags,api-design,Rest,Tags,Api Design,我正处在一个十字路口,决定标记应该是它们自己的资源还是注释的嵌套属性。这个问题涉及到RESTful设计和数据库存储 上下文:我有一个笔记资源。用户可以有很多笔记。每个音符可以有许多标记 功能目标: 我需要创建路由来执行以下操作: 1) 获取所有用户标签。类似于:GET/users/:id/tags 2) 删除与注释关联的标记。 3) 将标记添加到特定注释 数据/绩效目标 1) 获取用户标签应该很快。这是为了“自动建议”/“自动完成”。 2) 防止重复(尽可能多)。我希望尽可能地重用标记,以便能够

我正处在一个十字路口,决定标记应该是它们自己的资源还是注释的嵌套属性。这个问题涉及到RESTful设计和数据库存储

上下文:我有一个笔记资源。用户可以有很多笔记。每个音符可以有许多标记

功能目标: 我需要创建路由来执行以下操作:
1) 获取所有用户标签。类似于:
GET/users/:id/tags

2) 删除与注释关联的标记。
3) 将标记添加到特定注释

数据/绩效目标
1) 获取用户标签应该很快。这是为了“自动建议”/“自动完成”。
2) 防止重复(尽可能多)。我希望尽可能地重用标记,以便能够按标记查询数据。例如,我想缓解这样的场景:当标签“superhero”已经存在时,用户键入一个标签,如“superheros”

也就是说,在我看来,有两种方法可以在Notes资源上存储标记:

1) 标记作为嵌套属性。例如:

type: 'notes',
attributes: {
  id: '123456789',
  body: '...',
  tags: ['batman', 'superhero'] 
}
type: 'notes',
data: {
  id: '123456789',
  body: '...',
  tags: [1,2,3] // <= Tag IDs instead of strings
}
2) 标记作为自己的资源。例如:

type: 'notes',
attributes: {
  id: '123456789',
  body: '...',
  tags: ['batman', 'superhero'] 
}
type: 'notes',
data: {
  id: '123456789',
  body: '...',
  tags: [1,2,3] // <= Tag IDs instead of strings
}
type:'notes',
数据:{
id:'123456789',
正文:“…”,

标签:[1,2,3]/可能有点复杂。所以我可以分享我在
Tag
工作中的经验(在我们的例子中,这是VoIP应用程序的一个主要功能)

在任何情况下,所有的
标记都将是唯一的对象,其中包含大量信息。正如您所知,这将是一个更复杂的传输过程,但您需要这些信息,例如下面。当然,Json是最快的解决方案

type: 'notes',
data: {
  id: '123456789',
  body: '...',
  tags: [UUID1,UUID2,UUID3] 
}
例如,您需要多少信息。当您要根据标签率更改标签颜色或大小、根据数字使用情况更改颜色、链接(不相同)、重复等

type: 'tag',
data: {
  uuid: '234-se-324',
  body: 'superhero',
  linked: [UUID3, UUID4]
  rate: 4.6,
  usage: 4323
  duplicate: [superheros, suppahero]
}
正如您所看到的,我们甚至使用了重复项。只是为了保存每个
标记的唯一性。当然,我们也包含过滤单词Root的逻辑,但正如您从上面的示例中所看到的,我们还使用具有特殊根的重复值,如“Superhero”和“Suppahero”,它们对我们来说是相同的

您可能会想,这是很多关于“自动建议”或“自动完成”的信息,但我们从来没有遇到过性能问题(如果服务器端支持理智的话)。而且所有信息对于每次使用都很重要,在这种情况下,请注意。

tl;dr

考虑到您的需求,IMO应该将
标记
存储为资源,API应该返回
注释
,并将标记作为嵌入属性


数据库设计 将
注释
标记
作为单独的集合(或表格)保留。由于您有许多注释和许多标记,并且考虑到核心功能依赖于搜索/自动完成这些
标记
,这将提高搜索特定
标记的
注释
时的性能。非常基本的设计可以如下所示:

注释

{
    'id': 101,    // noteid
    'title': 'Note title',
    'body': 'Some note',
    'tags': ['tag1', 'tag2', ...]
}
{
    'id': 'tag1',    // tagid
    'name': 'batman',
    'description': 'the dark knight',
    'related': ['tagx', 'tagy', ...],
    'notes': [101, 103, ...]
}
标签

{
    'id': 101,    // noteid
    'title': 'Note title',
    'body': 'Some note',
    'tags': ['tag1', 'tag2', ...]
}
{
    'id': 'tag1',    // tagid
    'name': 'batman',
    'description': 'the dark knight',
    'related': ['tagx', 'tagy', ...],
    'notes': [101, 103, ...]
}
您可以使用
related
属性来处理重复项,方法是将
tagx
tagy
替换为类似的
标记


API设计 1.为
用户获取
注释

GET /users/{userid}/notes
GET /users/{userid}/tags
DELETE /users/{userid}/{noteid}/{tag}
PUT /users/{userid}/{noteid}/{tag}
在后端处理此路由时,将
标记
嵌入
注释
对象中。API发送的
注释
对象应如下所示:

{
    'id': 101,
    'title': 'Note title',
    'body': 'Some note',
    'tags': ['batman']    // replacing the tag1 by its name from tag collection
}
2.为
用户获取
标签

GET /users/{userid}/notes
GET /users/{userid}/tags
DELETE /users/{userid}/{noteid}/{tag}
PUT /users/{userid}/{noteid}/{tag}
如果不需要,您可以跳过发送
注释
属性,该属性包含
注释的
id

3.删除
注释的
标签

GET /users/{userid}/notes
GET /users/{userid}/tags
DELETE /users/{userid}/{noteid}/{tag}
PUT /users/{userid}/{noteid}/{tag}
4.为
注释添加
标签

GET /users/{userid}/notes
GET /users/{userid}/tags
DELETE /users/{userid}/{noteid}/{tag}
PUT /users/{userid}/{noteid}/{tag}
为了解决性能问题,为
用户
获取
标记应该很快,因为您有一个单独的集合。此外,处理重复项会更简单,因为您可以简单地添加类似的
标记
(通过
id
名称
)进入
相关的
数组。希望这有帮助


为什么不将标记保留为嵌套属性
  • 设计的可伸缩性不如前一种情况。如果
    标记
    是嵌套属性,并且必须编辑
    标记
    ,或者必须添加一些信息,则需要更改所有
    注释
    ,因为多个
    注释
    可以包含相同的
    标记
    。然而,保留
    标记
    e> 作为资源,相同的
    注释
    将与其
    ID
    进行映射,并且需要在
    标记
    集合/表格中进行单个更改

  • 处理重复的
    标记
    可能不像将它们作为单独的资源保存那样简单

  • 搜索
    标记时
    需要搜索每个
    注释
    中嵌入的所有
    标记
    。这会增加开销



使用
标记
作为嵌套属性IMO的唯一优点是,对于特定的
注释

如果希望所有数据都在同一行中,那么将标记保存为嵌套属性将更容易添加或删除
标记

在发票上添加项目

标题、说明、价格、数量、税费等

在这种情况下,税款可能是:增值税20%,因此您计算发票时使用20%,但一天的税款更改为22%,保存在DB上的所有发票将增加2%。在这种情况下,您添加新列并将其保存为原始数字20,当您从DB读取发票时,您将从一行获得所有数据,而不是从不同的表或va中计算流氓

标签也是一样的。如果你想去默格