如何为标签云设计MySql表?
-
25-09-2019 - |
题
我的网站上有文章,我想添加描述每篇文章的标签,但我在设计标签的 mysql 表时遇到问题。我有两个想法:
- 每篇文章都有“标签”字段,标签的格式为:“标签1,标签2,标签3”
- 创建其他名为标签的表,其中包含字段:标签名称、文章 ID
因此,当我想要 ID 为 1 的文章的标签时,我会运行
SELECT ... FROM tags WHERE `article_id`=1;
但是,我还想通过比较标签来了解 3 篇最相似的文章,所以如果我有一篇带有标签“php,mysql,erlang”的文章,以及 5 篇带有标签的文章:“php,mysql”,“erlang,ruby”,“php erlang”,“mysql,erlang,javascript”,我会选择1.,3.和 4.,因为这 3 个与主文章具有大多数相同的标签。
还有另一个问题,获得 10 个“最常用标签”的最佳方法是什么?
解决方案
一般来说,对于这种多对多关系,有三个表:
- 这 ”
article
“ 桌子- 主键=id
- 这 ”
tag
“ 桌子- 主键=id
- 包含每个标签的数据:
- 名称,例如
- A ”
tags_articles
“表,充当连接表,仅包含:id_article
:指向一篇文章的外键id_tag
:指向标签的外键
这样,任何标签的数据就不会重复:对于每个标签,在 tag
桌子。
并且,对于每篇文章,您可以有多个标签(即中的几行 tags_articles
桌子) ;当然,对于每个标签,您可以有几篇文章。
按照这个想法,获取文章的标签列表只需进行额外的查询,例如:
select tag.*
from tag
inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123
获得三篇“最相似”的文章意味着:
- 选择具有第一篇文章所具有标签的文章
- 只使用那些具有最重要数量的相同标签的标签
未经测试,但一个想法可能如下所示:
select article.id, count(*) as nb_identical_tags
from article
inner join tags_articles on tags_articles.id_article = article.id
inner join tag on tag.id = tags_articles.id_tag
where tag.name in ('php', 'mysql', 'erlang')
and article.id <> 123
group by article.id
order by count(*) desc
limit 3
基本上,你:
- 为初始文章中出现的每个标签选择文章 ID
- 因为存在内部联接,如果数据库中的一篇文章有 2 个与
where
条款,没有group by
子句,该文章将有两行 - 当然,您不想重新选择已有的文章——这意味着它必须被排除。
- 因为存在内部联接,如果数据库中的一篇文章有 2 个与
- 但是,当你使用
group by article.id
, ,每篇文章只有一行- 但你可以使用
count
, ,找出每篇文章与第一篇文章有多少个共同标签
- 但你可以使用
- 那么,只需按标签数量进行排序,并仅获取第三三行即可。
其他提示
首先,您需要使用 Pascal MARTIN 关于桌子设计的建议。
至于查找类似的文章,这里有一些可以帮助您入门的内容。假定 @article_id 是您要查找匹配项的文章,@tag1、@tag2、@tag3 是该文章的标签:
SELECT article_id, count(*)
FROM tags_articles
WHERE article_id <> @article_id
AND tag_id IN (@tag1, @tag2, @tag3)
GROUP BY article_id
ORDER BY count(*) DESC
LIMIT 3
是的,但是你没有回答我的主要问题,如何获得3篇最相似的文章?
回答:只需在合并表 (tags_articles) 中查找相同的标签 id 即可。收集它们并创建一个图案。
例如:第 1 条有标签:1,2第2条有标签:2,3,4 第5条有标签:6,7,2 第7条有标签:7,1,2,3
如果您想要第 1 篇文章中最相似的 3 篇文章,则必须查找标签 1,2。您会发现第 7 条最相似,第 2 条和第 5 条有一些相似之处。