Как реализовать поиск для системы тегов?

#php #mysql #search

#php #mysql #Поиск

Вопрос:

Многие типы систем используют теги для организации контента, включая блоги и 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» и «ужасный фильм». Я хочу, чтобы пользователи могли найти этот фильм, выполнив поиск по запросу «действие, страница 13, ужасный фильм».

Я взорву строку тегов в PHP, чтобы получить массив тегов:

 action
PG-13
terrible movie
  

Итак, мой вопрос в том, как мне использовать имена тегов для поиска фильмов с этими тегами? Фильмы могут иметь и другие теги, но должны быть возвращены только в том случае, если у них есть все теги в поиске.

Единственное решение, которое я могу придумать, — это денормализовать имя тега и сохранить его в movie_tags as well as movie_tag_options (т. Е. Добавить дублирующийся name столбец movie_tags ), а затем создать запрос на 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 и вставлены в запрос.

Недостатком этого подхода является хранение имен тегов в двух таблицах вместо одной.

Есть ли лучший способ?

Ответ №1:

или вы можете использовать

 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;