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