如何实现标签系统的搜索


How to implement search for a tagging system?

许多类型的系统使用标签来组织内容,包括博客和StackOverflow。假设我正在制作一个电影网站,并希望用户能够标记电影,以及使用标签组合搜索电影。

下面是一个示例数据库结构:
movies:
id, name
movie_tag_options (used to provide users with list of available tag options):
id, name
movie_tags:
id, m_id, mto_id

假设有一部电影叫《变形金刚9 -爆炸》,它的标签是"动作"、"PG-13"answers"恐怖电影"。我希望用户能够通过搜索"动作,PG-13,恐怖电影"来找到这部电影。

我将在PHP中扩展标签字符串以获得一个标签数组:

action
PG-13
terrible movie

那么我的问题是,我如何使用标签名称来查找具有这些标签的电影?电影也可以有其他标签,但只有当它们包含搜索中的所有标签时才应该返回。

我能想到的唯一解决方案是将标签名称反规范化并将其存储在movie_tags以及movie_tag_options中(即向movie_tags添加重复的name列),然后在PHP中构建查询,为每个标签生成JOIN语句。像这样:

SELECT id, name FROM movies
JOIN movie_tags mt0 ON mt0.name = "action"
JOIN movie_tags mt1 ON mt1.name = "PG-13"
JOIN movie_tags mt2 ON mt2.name = "terrible movie"

JOIN行将通过PHP生成并插入查询。

这种方法的缺点是将标记名称存储在两个表中,而不是一个表中。

有更好的方法吗?

或者使用

select a.name, count(c.id) c
from movies a
join movie_tags b on a.id = b.m_id
join movie_tag_options c on b.mto_id = c.id
where c.name in ('action', 'PG-13', 'terrible movie')
group by a.id
having c = 3;