据我所知的几种方法来实现标记;使用 TagID 和 ItemID 之间映射表 (在我看来,有意义但 does 缩放?),将固定的数目的可能的 TagID 列添加到 ItemID (似乎是个好主意),保持标记中的文本列的逗号分隔 (声音古怪,但无法正常工作)。我甚至听说有人建议一个稀疏的矩阵,再如何做标记名称增长正常?

我正在丢失了标记的最佳做法?

2008-08-21 19:18:05
问题评论:

好了,这是问题 #20856,(几乎) 同样的问题 #48475 要求至少两个星期之后问了这个问题。

另一个有趣的问题是"如何因此实现标记?"

另一个有趣的问题是"您是否国际化,以及如果是这样,如何?"

有趣的比较 (Postgres 特定)︰ databasesoup.com/2015/01/tag-all-things.html

请参阅stackoverflow.com/questions/48475/database-design-for-tagging

回答:

三个表 (一个存储的所有项目,所有的标记,和两者之间的关系),正确编制索引,设置适当的数据库上运行的外键应该运行良好,而且正确缩放。

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID

我认为这可能是足够的 upvoted。这显然是做的最好办法。

清楚吗?其中,是这是显然的最佳方法来执行此操作 (除非这一事实,就标准化的同时,记住规范化是快速插入、 慢的选择) 的证据。

这被称为"Toxi"的解决方案,您可以找到更多有关它的信息在此处︰ pui.ch/phred/archives/2005/04/tags-database-schemas.html

此处未显示的一件事是层次结构的"标记"或标记表中的类别。这通常需要在类别和子类别但需要灵活地进行标记的网站上。例如,食谱网站自动部件站点、 业务目录等。因此标记是答案,但您需要使用一些像嵌套集模型或邻区列表模型标记表中,这些类型的数据通常不适合到只有一个单一的类别。

我与 HK1 agrree 是它可能具有上述结构 + 表︰ TagGroup 列︰ TagGropuId,标题表︰ 标记列︰ TagID,标题,TagGroupId

通常我会同意 Yaakov Ellis,但在此特殊的情况下没有其他可行的解决方案︰

使用两个表︰

Table: Item
Columns: ItemID, Title, Content
Indexes: ItemID

Table: Tag
Columns: ItemID, Title
Indexes: ItemId, Title

这有一些主要优点︰

首先它使开发变得更加简单︰ 您需要对插入和更新item的三个表格解决方案中查找Tag表,以查看是否已有条目。然后您必须将它们联接起来用新的。这是不重要的任务。

然后它使查询更简单 (可能更快)。有三个主要数据库查询,您将执行此操作︰ 一Item输出所有的Tags、 绘制标记云和一个标记标题选择的所有项目。

对于一个项目的所有标记︰

表 3:

SELECT Tag.Title 
  FROM Tag 
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 WHERE ItemTag.ItemID = :id

表 2:

SELECT Tag.Title
FROM Tag
WHERE Tag.ItemID = :id

标签云︰

表 3:

SELECT Tag.Title, count(*)
  FROM Tag
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 GROUP BY Tag.Title

表 2:

SELECT Tag.Title, count(*)
  FROM Tag
 GROUP BY Tag.Title

一个标记的项︰

表 3:

SELECT Item.*
  FROM Item
  JOIN ItemTag ON Item.ItemID = ItemTag.ItemID
  JOIN Tag ON ItemTag.TagID = Tag.TagID
 WHERE Tag.Title = :title

表 2:

SELECT Item.*
  FROM Item
  JOIN Tag ON Item.ItemID = Tag.ItemID
 WHERE Tag.Title = :title

但也有一些缺陷,太︰ 可能花费更多的空间数据库 (这可能会导致更多的磁盘操作慢),并且它不具有规范化这可能会导致不一致的情况。

Size 参数是不强的标记的本质就是它们通常很小,因为这样的大小增加不更大的一个。有人可能会说的查询的标签标题中较小的表,其中包含每个标记一次更快,并且当然也是如此。但是,在考虑采取节约不让加入,您可以在其上生成好的索引的事实无法轻松地弥补此。这当然取决于很大程度上所使用的数据库的大小。

不一致的参数也是一些没有任何意义。标记是自定义文本字段并没有重命名所有标记为"栏"的"foo"正如预期的操作。

因此 tldr︰ 我会为两个表解决方案。(事实上,我要到。我发现这篇文章,以了解是否有针对它的有效参数)。

Does"索引︰ ItemId、 标题"意味着每个或一个同时包含这两者的索引的索引?

正常情况下两个索引。无法取决于您正在使用,但该数据库。

在标记表是 ItemId 并标记一个复合键?或者您是否也 PK?

我认为这取决于您正在使用的框架的种类 / 如何使用您编写的代码。一段时间内轻松地具有主键,并且有时它不是。在本例中我确实有 PK,因为我喜欢更多使用一些喜欢删除? id = 5 比删除? idemid = 3 和标记 = Foo web 客户端中。从数据一致性的角度看另一方面岂不使用额外的 PK.为教学目的而不是建议它:)

关于 Scheintod 的两个表的解决方案,它应起的作用,但仍有一些限制。1.如果您的标签具有与之关联 (例如,如果您的标签说明或某些其他数据) 的任何数据乘标记的对象可能没有它们而无需进行大量的工作,以使它们保持同步以一致的方式编辑的元数据。2.较一些额外的存储空间时有长标题和标签使用多次。在 2 表解决方案中,标题将重新输入次数多。也许某些数据库将优化数据作为其存储/索引,但我不敢肯定。在我种情况下,

如果您使用支持的数据库映射减少,像 couchdb,纯文本字段或字段列表中的存储标签确实是最佳方式。示例︰

tagcloud: {
  map: function(doc){ 
    for(tag in doc.tags){ 
      emit(doc.tags[tag],1) 
    }
  }
  reduce: function(keys,values){
    return values.length
  }
}

运行此组 = true 将结果分组按标记名称和甚至返回时遇到的标记的次数的计数。它是单词的非常类似于对文本中的出现次数计数.

+ 此外看到有些 NoSQL 实现的 1 不错。

@NickRetallack 链接无法正常工作。如果可能,请更新此答案。

好了我用到 archive.org 替换链接

使用一个带格式的文本栏 [1] 存储标记并能够完整文本搜索引擎用于索引这。否则就会出现试图实现布尔查询时缩放问题。

如果您需要有关您的标记的详细信息,您可以的跟踪增量维护的表中或运行批处理作业中提取信息。

[1] 有些 RDBMS 甚至提供本机数组类型,它可能会更好适合存储不需要分析的步骤,但可能会导致使用全文搜索的问题。

您是否知道任何全文搜索引擎,找不到的单词上的变化?例如,书籍搜索不会返回书籍吗?此外,您该怎么办关于"c + +"等标记?例如,,SQL Server 会在索引中去除加号。谢谢。

请尝试 Sphinx- sphinxsearch.com

也许有用的那些人将此路由 (全文搜索) 本 3 部分教程。它使用 PostgreSQL 本机设备︰ shisaa.jp/postset/postgresql-full-text-search-part-1.html

我已经始终保持在一个单独的表中的标记,然后必须映射表。当然我已经永远不会进行任何真正大规模也。

"标记"表和映射表使得相当简单,以生成 tag cloud 和此类,因为您可以轻松地组建了 SQL 来获取与每个标签使用的频率计数的标记的列表。

这是更容易,如果您未使用映射表:)

请输入您的翻译

Recommended SQL database design for tags or tagging [closed]

确认取消