【问题标题】:How to implement a multi-user tag *voting* system (i.e. like Slashdot's story tags)如何实现一个多用户标签*投票*系统(即像 Slashdot 的故事标签)
【发布时间】: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


【解决方案1】:

这是一个更简洁的查询:

SELECT
   doc_id, 
   tag_id,
   COUNT(*) AS num_times_tagged, 
   COUNT(DISTINCT user_id) AS taggers_count,
   COUNT(*)/COUNT(DISTINCT user_id) AS popularity

FROM doc_tag
GROUP BY doc_tag.doc_id, doc_tag.tag_id

另外,我不熟悉所有 RBDMS,但如果您使用的是 Sql Server,您可以创建一个视图,然后在视图之上创建一个聚集索引。这会减慢您对 doctag 的插入速度,但会使您从该视图读取的速度非常快。

【讨论】:

    猜你喜欢
    • 2013-07-22
    • 2017-11-15
    • 2010-12-21
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多