原文来自:Then each went to his own home
原文作者:Philipp Keller
中文翻译:icyleaf
译者注:本文在涉及到专业术语或者译者表达不明白的地方均会保留原英文。
最近,在del.icio.us mailinglist(译者按:应该是美味书签的讨论版块。以下del.icio.us翻译为美味书签)上面发了一个问题:“有人知道美味书签的数据库设计吗?”。之后我得到了一些回复,所以我想把这部分东西的知识分享给大家。
当你要为一个书签添加你认为需要的一个或多个标签时(或日志或其他)其数据库是如何设计的?然后,执行查询时取消这些书签中标签的合集(union)或交集(intersection)。也能从搜索结果中减少一些标签。
大致有三种不同的解决方案:(注意:如果你开发了一个网站使得任何人都可以添加标签,而且是一个较大规模的网站则请务必看下其作者写的另外一篇文章:标签系统的性能测试)
在这个方法中仅架构了一个表,它是去规范化(denormalized)表。
这个类型被叫做“MySQLicious 方法(solution)”,因为MySQLicious使用这种结构可以把美味书签的数据导入到一个表中。
译者注:MySQLicious是一个把del.icio.us书签镜像到MySQL数据库中的工具。
查询方式: “search+webservice+semweb”:
SELECT * FROM `delicious` WHERE tags LIKE "%search%" AND tags LIKE "%webservice%" AND tags LIKE "%semweb%"
查询方式: “search|webservice|semweb”:
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"
查询方式: “search+webservice-semweb”
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"
优点:
缺点:
分离(Scuttle)字段,并归类到两个表中。右图表“scCategories”是一个标签表,通过一个外来的ID链接书签表。
查询方式:“bookmark+webservice+semweb”:
首先,当搜索的标签为“bookmark”,“webservice“或“semweb”(例如:c.category IN ('bookmark', 'webservice', 'semweb')
)时所有名为"bookmark"的标签都会被搜索,然后所有包含这三个标签的书签将筛选出来 (HAVING COUNT(b.bId)=3
).
查询方式:“bookmark|webservice|semweb”:
Just leave out the HAVING
clause and you have union:
查询方式:“bookmark+webservice-semweb”,意味着:bookmark AND webservice AND NOT semweb.
省略掉 HAVING COUNT
会导致搜索方式变为“bookmark|webservice-semweb”.
信息来源:Rhomboid写的helping me out with this query.
我猜测这个解决方案主要有利点是使得他更正常化,比第一个解决方案比较而言,好处在于可以为每一个书签添加无限数量的标签。
Toxi 提出了一个三个表的结构,通过表”tagmap“的书签和标签的n-to-m关联。每一个标签都可以在不同的书签一期使用,反之亦然。这种数据库结构也被用在Wordpress之中。
查询方式:“bookmark+webservice+semweb”
查询方式:“bookmark|webservice|semweb”
查询方式:“bookmark+webservice-semweb”,意味:bookmark AND webservice AND NOT semweb.
省略掉 HAVING COUNT
会导致搜索方式变为“bookmark|webservice-semweb”.
信息来源:Rhomboid写的helping me out with this query.
优点:
缺点:
如果你想要更复杂的查询,比如”(bookmarks OR bookmark) AND (webservice or WS) AND NOT (semweb or semanticweb)“这样的查询语句,我建议参见以下查询/计算过程:
SELECT b.id FROM tagmap bt, bookmark b, tag t WHERE bt.tag_id = t.tag_id AND b.id = bt.bookmark_id AND t.name = "semweb"
通过这种方式,你也可以查询"(del.icio.us|delicious)+(semweb|semantic_web)-search",这种类型的查询(即,括号内)利用去规范化的
“MySQLicious solution”不能这样做。
这是最灵活的数据结构和我猜想它的效果相当好(即,使用一些缓存技术)。
2006年5月更新:这篇文章获得了大家的注视。我真的不是为此而准备的!看来大家不断的提到了他,甚至一些网站转载我的文章,我认为,这些不同方式的理论的知识应该归功于:MySQLicious, scuttle, Toxi以及所有参与并贡献的评论者(请务必阅读!)
p.s. 感谢Toxi发给我关于三个表结构的疑问,Benjamin Reitzammer为我指点的文章(一个很好的标签查询参考)和powerlinux提供的scuttle指引。
Taglist: a mailing list dedicated to schemas with tagging Tagschema: A blog dedicated to tagging schemas Tag-related Queries on Snippets Freetag is a php “library” with which you can add tags to whatever object you like. It actually uses the “toxi schema”. Hammy gives an insight how he did his tagging system with “less DB and more code” (that is: regular expressions), interesting! Brad Choate has got some ideas which tag queries should be possible Feedmaker has written a sort of reply to this article