【发布时间】:2010-08-10 07:31:43
【问题描述】:
这个问题与典型的“我如何制作标记系统”问题有点不同,后者已在 SO 和其他地方进行了深入讨论。
我想众包标记,这样您就不必依赖每个文档的所有者来完全列出适用的标记。同时,我不希望一个随机的 schmoe 能够通过故意错误标记大量文档来弄乱每个人的标签。
这样的系统一般是如何工作的?例如,Slashdot.org 依靠类似这样的东西来提供故事标签。 (从来没有编辑过标签,我有兴趣了解更多关于它是如何工作的。)
现在让这个更具体:假设我的标记数据库架构如下所示:
doc: id, name, ...
tag: id, tag_name
doc_tag: doc_id, tag_id, user_id
现在,每个用户都可以为文档分配他/她自己的标签。确定共识的一种方法是查看使用特定标签标记文档的人的比例。这会导致下面的 SQL 语句异常。
SELECT
doc_id, tag_id,
num_times_tagged, taggers_count,
num_times_tagged/taggers_count AS popularity
FROM doc_tag
LEFT JOIN (
SELECT doc_id, tag_id, COUNT(*) AS num_times_tagged
FROM doc_tag GROUP BY doc_id, tag_id
) num_times
ON doc_tag.doc_id = num_times.doc_id AND
doc_tag.tag_id = num_times.tag_id
LEFT JOIN (
SELECT doc_id, COUNT(DISTINCT user_id) AS taggers_count
FROM doc_tag GROUP BY doc_id
) num_taggers
ON doc_tag.doc_id = num_taggers.doc_id
GROUP BY doc_tag.doc_id, doc_tag.tag_id
我这样做完全错了吗?这似乎是一个非常昂贵的查询。假设我只想获得一份文档列表和每个文档的顶级标签——我什至如何为此编写一个连接?我不想对获得的每个文档都运行此查询!
感谢您的建议。
大卫
【问题讨论】:
-
如果您想减少查询时间(选择)的负载,您可以在人们重新标记时使用触发器来更新帮助表。这个帮助表可以是精简的、正确索引的等等,并且可以快速加载。这会将负载转移到不同的时刻,可能会给你一个不太干净/KISS 数据模型,但这是一种选择。
-
嗯——我以前没用过触发器。你能举例说明这可能是什么样子吗?辅助表模式是什么——标签 ID、文档 ID、#count?
-
链接后面是对触发器的介绍。 sqlteam.com/article/an-introduction-to-triggers-part-i 。至于辅助表模式:这取决于您真正想要展示的内容,但您的示例可能是一个开始(也许是您所需要的全部)。
标签: sql database-design tagging