首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实现标签系统

如何实现标签系统
EN

Stack Overflow用户
提问于 2009-11-28 03:35:39
回答 7查看 31.6K关注 0票数 93

我想知道实现标记系统的最好方法是什么,就像在SO上使用的那样。我正在考虑这一点,但我想不出一个好的可伸缩的解决方案。

我在考虑一个基本的3表解决方案:有一个tags表,一个articles表和一个tag_to_articles表。

这是这个问题的最佳解决方案吗,还是有其他选择?使用这种方法,表将在时间上变得非常大,并且对于搜索,我认为效率不是太高。另一方面,查询的执行速度并不是很重要。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-11-28 04:18:40

我相信你会发现这篇博文很有趣:Tags: Database schemas

问题:您希望有一个数据库模式,在该模式中,您可以使用任意多的标记来标记书签(或博客文章或其他内容)。然后,您希望运行查询来将书签约束到标记的并集或交集。你还想从搜索结果中排除(比如:减去)一些标签。

“MySQLicious”解决方案

在这个解决方案中,模式只有一个表,它是反规范化的。这种类型被称为“MySQLicious解决方案”,因为MySQLicious将del.icio.us数据导入到具有这种结构的表中。

“search+webservice+semweb”的交集(AND)查询:

代码语言:javascript
复制
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"

|webservice|semweb”的搜索联合(OR)查询:

代码语言:javascript
复制
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"

+webservice-semweb”的搜索减号查询

代码语言:javascript
复制
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"

“天窗”解决方案

Scuttle将其数据组织在两个表中。表“scCategories”是“标记”-table,并且具有指向“书签”-table的外键。

“bookmark+webservice+semweb”:的交集(AND)查询

代码语言:javascript
复制
SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId
HAVING COUNT( b.bId )=3

首先,搜索所有书签-标签组合,其中标签是“bookmark”、“webservice”或“semweb”(c.category IN ('bookmark','webservice','semweb')),然后仅考虑已经搜索到所有三个标签的书签(具有计数(b.bId)=3)。

“bookmark|webservice|semweb”:Union (OR)查询只需省略HAVING子句,您就有了union:

代码语言:javascript
复制
SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId

减去(排除)查询“bookmark + webservice -semweb”,即:书签和webservice,而不是semweb.

代码语言:javascript
复制
SELECT b. *
FROM scBookmarks b, scCategories c
WHERE b.bId = c.bId
AND (c.category IN ('bookmark', 'webservice'))
AND b.bId NOT
IN (SELECT b.bId FROM scBookmarks b, scCategories c WHERE b.bId = c.bId AND c.category = 'semweb')
GROUP BY b.bId
HAVING COUNT( b.bId ) =2

省略HAVING计数的将导致查询“bookmark|webservice-semweb”.

“Toxi”解决方案

Toxi提出了一个三表结构。通过表“tagmap”,书签和标签是n对m相关的。每个标签可以与不同的书签一起使用,反之亦然。wordpress也使用这个DB-schema。查询与“scuttle”解决方案中的查询完全相同。

“bookmark+webservice+semweb”交集(AND)查询

代码语言:javascript
复制
SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id
HAVING COUNT( b.id )=3

“|webservice|semweb”的书签联合(OR)查询

代码语言:javascript
复制
SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id

减去(排除)查询“bookmark + webservice -semweb”,即:书签和webservice,而不是semweb.

代码语言:javascript
复制
SELECT b. *
FROM bookmark b, tagmap bt, tag t
WHERE b.id = bt.bookmark_id
AND bt.tag_id = t.tag_id
AND (t.name IN ('Programming', 'Algorithms'))
AND b.id NOT IN (SELECT b.id FROM bookmark b, tagmap bt, tag t WHERE b.id = bt.bookmark_id AND bt.tag_id = t.tag_id AND t.name = 'Python')
GROUP BY b.id
HAVING COUNT( b.id ) =2

省略HAVING计数的将导致查询“bookmark|webservice-semweb”.

票数 122
EN

Stack Overflow用户

发布于 2009-11-28 03:41:13

您的三表解决方案没有任何问题。

另一种选择是限制可应用于文章的标签数量(如SO中的5个),并将这些标签直接添加到您的文章表中。

规范化数据库有其优点和缺点,就像将事物硬连接到一个表中一样也有优点和缺点。

没有人说你不能同时做到这两点。重复信息与关系数据库范式背道而驰,但如果目标是性能,您可能必须打破范式。

票数 8
EN

Stack Overflow用户

发布于 2009-11-28 18:27:44

您提议的三个表实现将用于标记。

但是,堆栈溢出使用不同的实现。它们将标签以纯文本形式存储到帖子表的varchar列中,并使用全文索引来获取与标签匹配的帖子。例如posts.tags = "algorithm system tagging best-practices"。我相信Jeff在什么地方提到过这一点,但我忘了在哪里了。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1810356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档