В MySQL Поиск По Нескольким Таблицам
у меня есть три таблицы в базе данных MySQL, используемой в приложении музыкальной библиотеки:
на Genre таблица имеет столбцы:
- id
- 
title(строка)
на Album таблица имеет столбцы:
- id
- 
genre_id(внешний ключGenre.id)
- 
title(строка)
- 
artist(строка)
и Track таблица колонки:
- id
- 
album_id(внешний ключAlbum.id)
- 
title(строка)
каждого Album может иметь любое количество Tracks, каждый Track один Album и друг Album один Genre.
я хочу реализовать поиск по ключевому слову, который позволяет пользователю вводить любое количество ключевых слов и найти все Tracks что:
- есть соответствие title,
- на AlbumС соответствующимtitleилиartist,
- или AlbumСGenreС соответствующимtitle.
результаты должны быть отсортированы по релевантности.  Было бы здорово, если бы каждое поле имело рейтинг релевантности. Например,title of a Track может быть важнее, чем title на Genre.
кроме того, решение должно использовать некоторую форму частичного поиска. Поиск rubber должен сначала соответствовать всем Tracks С title of Rubber, затем Tracks С title соответствующего *rubber* (* =подстановочный знак), затем перейдите к Albums и так далее. Однако я не очень-то настаиваю на этих деталях. Я просто ищу более общее решение, которое я могу настроить в соответствии с моими конкретными потребностями.
я также должен упомянуть, что я использую стек LAMP, Linux, Apache, MySQL и PHP.
каков наилучший способ реализации этого ключевого слова поиск?
обновление: я пытался реализовать это с помощью полнотекстового поиска и придумал следующие инструкции SQL.
CREATE TABLE `Genre` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` text NOT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
INSERT INTO `Genre` VALUES(1, 'Rock');
CREATE TABLE `Album` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `genre_id` int(11) NOT NULL,
  `title` text NOT NULL,
  `artist` text,
  PRIMARY KEY (`id`),
  FULLTEXT KEY (`title`, `artist`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
INSERT INTO `Album` VALUES(1, 1, 'Rubber Soul', 'The Beatles');
CREATE TABLE `Track` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `album_id` int(11) NOT NULL,
  `title` text NOT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
INSERT INTO `Track` VALUES(1, 1, 'Drive My Car');
INSERT INTO `Track` VALUES(2, 1, 'What Goes On');
INSERT INTO `Track` VALUES(3, 1, 'Run For Your Life');
INSERT INTO `Track` VALUES(4, 1, 'Girl');
3 ответов
Я хотел бы использовать Apache Solr. Используйте Обработчик Импорта Данных чтобы определить SQL-запрос, который объединяет все таблицы вместе, создайте полнотекстовый индекс из результата объединенных данных.
столбцы с именем args to MATCH () должны быть столбцами, определенными для индекса, в том же порядке, что и в индексе. Но вы не можете определить какой-либо индекс (полный текст или иначе) через несколько таблиц в MySQL.
Так что вы не можете сделать это:
WHERE MATCH (g.title, a.title, a.artist, t.title) AGAINST ('beatles')
не имеет значения, используете ли вы логический режим или режим естественного языка.
вам нужно сделать это:
WHERE MATCH (g.title) AGAINST ('beatles')
   OR MATCH (a.title, a.artist) AGAINST ('beatles')
   OR MATCH (t.title) AGAINST ('beatles')
вы также можете быть заинтересованы в моей презентации практический полнотекстовый поиск в MySQL.
определите полнотекстовый индекс для четырех столбцов, которые вы хотите найти, а затем выполните:
SELECT * FROM genre AS g
  LEFT JOIN album AS a ON g.id = a.genre_id
  LEFT JOIN tracks AS t ON a.id = t.album_id
  WHERE MATCH (g.title,  a.title, a.artist, t.title) AGAINST ('searchstring');
в resullt будут отсортированы по релевантности. Подробнее о полнотекстовом поиске см. здесь: http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html
Я бы использовал что-то вроде Сфинкса, u может сделать индекс из вашего запроса, а затем запросить это. Это немного сложно, чтобы получить вашу голову вокруг, но результаты в 10 раз лучше, чем mysql против, и у вас не будет проблем позже со скоростью.
