如何为 RDBMS 中的多个表实现标记系统?

How to Implement a Tagging System for multiple tables in an RDBMS?

假设您有任意数量的 table,您希望允许用户附加 tag。例如,Whosebug 让我们可以标记一个问题,但也许它也可以让我们标记一个答案、一份工作、我们的用户个人资料等。

实施它的最佳方式是什么,做出此决定需要哪些信息?

在每个 table 标记和 tag table

之间创建一个 M:N
 +----<tag_foo>----foo
 |
tag
 |
 +----<tag_bar>----bar

找到所有带有标签 = 'rdbms'

的 Foos
SELECT foo.*
FROM tag JOIN tag_foo ON (tag.id = tag_foo.tag_id)
         JOIN foo ON (tag_foo.foo_id = foo.id)
WHERE tag.name = 'rdbms';

使用ClassTable继承

在这个方法中,我们做了一个taggable table,每个table to tag都有一个FK回到taggable并且是1:1 taggabletag table 有一个带有 `taggable.

M:N
                            +-------foo
                            |
tag----<tag_taggable>----taggable
                            |
                            +-------bar

找到所有带有标签 = 'rbdms'

的 Foos
SELECT foo.*
FROM tag JOIN tag_taggable ON (tag.id = tag_taggable.id)
         JOIN taggable ON (tag_taggable.taggable_id = taggable.id)
         JOIN foo ON (taggable.id = foo.id)
WHERE tag = 'rdbms';

这是 taggable 的 CREATE TABLE:

CREATE TABLE taggable (
    id INTEGER PRIMARY KEY,
    type VARCHAR NOT NULL CHECK (type IN ('foo', 'bar'))
)

我会选择第一个选项。第二个选项将强制您使用相同的列作为所有可标记 table 的主键,并将强制您为插入 foo 或 bar 的每条记录向可标记 table 插入一条记录。这将使插入更加麻烦,并且与多对多 table 相比没有真正的好处。当然,系统中的 table 少了,但每条记录的工作量增加了。

1:1 关系在您需要存储具有不同属性但都共享一些共同属性的多个项目时很有用。 例如,与猫、狗、狮子和斑马有关的动物。

它在标记系统中的用处不大,因为所有可标记实体的唯一共同点就是它们都是可标记的。