我已经看到很多关于构建对象标记的数据库模式的帖子(例如dlamblin's post和Artilheiro's post)。
我在很多天的研究中似乎找不到的是实现标记模式的模式逻辑,允许将标记分配给用户(例如LinkedIn的Skills and Expertise系统,其中包含标签用户添加的内容可以编入索引和搜索)。这可能就像将“对象”更改为用户一样简单,但我觉得它比这更复杂。
我希望能够构建几乎完全相同的东西,除了类别。例如,如果我们掌握了LinkedIn的一些技能并对其进行了分类,我们可能会有类似的东西:IT /计算,零售,项目管理等。
我知道有几种常用的方法和架构可用于对数据进行分类,特别是Nested Set
和Adjacency List
。我听过很多关于两者的事情,例如“嵌套集的插入和删除是资源密集型的”,“邻接列表模型很笨拙,有限,并且不包括无限深度。”
所以我有两个问题包含在一篇文章中:
粗略示例架构在向用户标记技能方面会是什么样子,可以对其进行索引和搜索,甚至可以为特定用户构建用户池标记
鉴于必须进行分类,对这种性质进行分类的最佳方法是什么?
是否还有其他适合我的模型,我不知道? (哎呀,我认为这是三个问题)
答案 0 :(得分:1)
我认为最好的逻辑与你链接的帖子中的状态相同
+------- +
| user |
+------- +
| userid |
| ... |
+--------+
+-------- --+
| linktable |
+-----------+
| userid | <- (fk and pk)
| tagid | <- (fk and pk)
+-----------+
+-------+
| tag |
+-------+
| tagid |
| ... |
+-------+
非常随意去imo。如果您想对标签进行分类,您可以将类别表分类到标签表
答案 1 :(得分:1)
你没有说哪个数据库,所以我将扮演魔鬼的拥护者,并建议它如何在MongoDB中运行。像这样创建您的用户:
db.users.insert({
name: "bob",
skills: [ "surfing", "knitting", "eating"]
})
然后创建“技能”索引。 Mongo会将数组中的每个技能添加到索引中,从而允许快速查找。查找具有2种技能的交集的用户具有与SQL数据库类似的性能,但语法更好:
db.users.find({skills: "$in": ["surfing", "knitting"]})
好处是单个磁盘搜索将获取用户所需的所有信息。缺点是需要更多的磁盘空间和更多的RAM。但如果它可以避免由连接引起的磁盘搜索,那么它可能是一个胜利。
答案 2 :(得分:1)
鉴于分类的必要性,对这种性质进行分类的最佳方法是什么?
取决于您需要多大的灵活性。例如,如果您可以假设类别层次结构的深度具有固定限制(例如1或2级),则邻接列表可能完全正常。
是否还有其他适合我的模型,我不知道?
路径枚举是一种在祖先名称的连接列表中表示层次结构的方法。因此,每个子类别标签不仅会命名自己的名称,还会命名其父级以及直到根的任何其他祖父母。
您已熟悉任何shell环境中的绝对路径名:“/ usr / local / bin”是“usr”,“local”和“bin”的路径枚举,它们之间的层次关系按顺序编码的字符串。
此解决方案也存在数据异常的可能性 - 您有责任为“/ usr / local”和“/ usr / local / bin”创建条目,如果不这样做,有些事情就会开始破坏
关于向用户标记技能,可以对其进行索引和搜索,甚至能够为特定标记构建用户池,粗略的示例模式会是什么样的?
在数据库中实现此操作几乎与单独命名标记一样简单,但它要求您的标记“name”列足够长以存储层次结构中的最长路径。
CREATE TABLE taguser (
tag_path VARCHAR(255),
user_id INT,
PRIMARY KEY (tag_path,user_id),
FOREIGN KEY (tag_path) REFERENCES tagpaths (tag_path),
FOREIGN KEY (user_id) REFERENCES users (user_id)
);
索引与简单标记完全相同,但如果从层次结构的根指定整个字符串,则只能搜索子类别标记。
SELECT user_id FROM taguser WHERE tag_path = '/IT/Computing'; -- uses index
SELECT user_id FROM taguser WHERE tag_path LIKE '%/Computing'; -- can't use index