В 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 против, и у вас не будет проблем позже со скоростью.