MySQL полнотекстовый поиск по нескольким таблицам с разными полями - PullRequest
2 голосов
/ 02 июля 2010

Я пытаюсь объединить несколько таблиц и выполнить полнотекстовый поиск по ним.

Большинство таблиц не связаны, но имеют похожие поля.

У меня работает полнотекстовый поиск, но мне нужно иметь возможность создавать ссылки из результатов, что является следующим шагом, но я неэто не сработает, потому что у меня нет достаточно полей, чтобы получить достаточно информации.

В основном я хочу найти заголовок и содержимое каждой таблицы, но я также хочу искать в моих таблицах форума, которыетемы и сообщения.Таблицы тем и сообщений связаны между собой.

Этот запрос поможет, не запрашивая таблицы форумов, но должен иметь возможность искать эти таблицы.

SELECT * FROM (SELECT title, content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM news WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM events WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM blogs WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM honeylands WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM articles WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM info WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT topicid as title, boardid as content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM articles WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)
    UNION ALL
    SELECT topicid as title, message as content,
    MATCH(title, content) AGAINST('folk*' IN BOOLEAN MODE)
    as score FROM info WHERE MATCH(title, content) 
    AGAINST('folk*' IN BOOLEAN MODE)) a ORDER BY score DESC

Я должен быть в состояниисоздайте ссылки для таблиц с именами полей commom, таких как events.php? id = 1, получая идентификатор из записи, но как мне это сделать для тем таблиц и сообщений topic.php? boardid = 1 & topic = 2?

Вот моя структура таблицы CREATE TABLE articles (id int (4) NOT NULL auto_increment, title varchar (70) NOT NULL по умолчанию '', content текст NOT NULL, ПЕРВИЧНЫЙ КЛЮЧ (id));

     CREATE TABLE `blogs` (
       `id` int(3) NOT NULL auto_increment,
       `title` varchar(100) NOT NULL default '',
       `content` text NOT NULL,
       PRIMARY KEY  (`id`)
     );

     CREATE TABLE `events` (
       `id` int(11) NOT NULL auto_increment,
       `title` varchar(100) NOT NULL default '',
       `content` text NOT NULL,
       PRIMARY KEY  (`id`)
     );

     CREATE TABLE `honeylands` (
       `id` int(4) NOT NULL auto_increment,
       `title` varchar(100) NOT NULL default '',
       `content` text NOT NULL,
       PRIMARY KEY  (`id`)
     );

     CREATE TABLE `info` (
       `id` int(1) NOT NULL auto_increment,
       `title` varchar(50) NOT NULL default '',
       `content` text NOT NULL,
       PRIMARY KEY  (`id`)
     );

     CREATE TABLE `messages` (
       `messageid` int(6) NOT NULL auto_increment,
       `boardid` int(2) NOT NULL default '0',
       `topicid` int(4) NOT NULL default '0',
       `message` text NOT NULL,
       `author` varchar(255) NOT NULL default '',
       `postdate` datetime default NULL,
       PRIMARY KEY  (`messageid`)
     );

     CREATE TABLE `news` (
       `id` int(4) NOT NULL auto_increment,
       `title` varchar(100) NOT NULL default '',
       `content` text NOT NULL,
       PRIMARY KEY  (`id`)
     );


     CREATE TABLE `topics` (
       `topicid` int(4) NOT NULL auto_increment,
       `boardid` int(2) NOT NULL default '0',
       `topicname` varchar(255) NOT NULL default '',
       `author` varchar(255) NOT NULL default '',
       `counter` int(5) NOT NULL default '0',
       `sticky` char(1) NOT NULL default 'n',
       `locked` char(1) NOT NULL default 'n',
       PRIMARY KEY  (`topicid`)
     );

Так я в настоящее время получаю все записи, но нет никакого способа добавить дополнительные поля для таблиц тем и сообщений, используя UNION

SELECT * FROM (SELECT title, content,
    MATCH(title, content) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM news WHERE MATCH(title, content) 
    AGAINST('$keywords*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM events WHERE MATCH(title, content) 
    AGAINST('$keywords*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM blogs WHERE MATCH(title, content) 
    AGAINST('$keywords*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM honeylands WHERE MATCH(title, content) 
    AGAINST('$keywords*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM articles WHERE MATCH(title, content) 
    AGAINST('$keywords*' IN BOOLEAN MODE)
    UNION ALL
    SELECT title, content,
    MATCH(title, content) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM info WHERE MATCH(title, content) 
    AGAINST('$keywords*' IN BOOLEAN MODE)
    UNION ALL
    SELECT topicname as title,message as content,
    MATCH(topicname, message) AGAINST('$keywords*' IN BOOLEAN MODE)
    as score FROM topics t INNER JOIN messages m ON t.topicid=m.topicid  
    WHERE MATCH(topicname, message) 
    AGAINST('$keywords*' IN BOOLEAN MODE)) a ORDER BY score DESC

1 Ответ

3 голосов
/ 02 июля 2010

Я сталкивался с этой проблемой при создании поиска на веб-сайте с несколькими типами контента (база данных фильмов).Я хотел, чтобы пользователь мог выполнить один поиск и найти имя актера, фильма или персонажа.

Вместо того, чтобы пытаться получить один большой оператор SQL, я сопоставил каждый тип контента (movie_title,movie_plot, actor_name, character_name и т. д.) и вставил идентификатор строки, тип содержимого и счет совпадения в многомерный массив.Обычно я ограничиваю каждый тип контента до 50 лучших совпадений.

Затем я смог отсортировать массив на основе оценки.Затем я использовал бы идентификатор и тип контента для поиска информации, которая мне была нужна для каждого результата.

РЕДАКТИРОВАТЬ (добавление кода)

Отказ от ответственности: Это старый код, и, вероятно, он более эффективенспособы сделать это

$topResults = array();
$topResults[0] = array('nil', 'nil', 0);

$movieFound = 0;
$plotFound = 0;
$actorFound = 0;
$characterFound = 0;

// example of movie title... follow the same procedure for the others
$sql = "SELECT movies.Movie_ID as mid, MATCH (Movie_Title) AGAINST ('$searchstring') AS Score FROM movies, Rating_Movie_Relationships WHERE MATCH (Movie_Title) AGAINST ('$searchstring') AND Front_Image_File IS NOT NULL AND movies.Movie_ID = Rating_Movie_Relationships.Movie_ID $sqlwhere ORDER BY Score DESC LIMIT 0, 20";
$result = @mysql_query($sql);
while ($row = mysql_fetch_array($result)) {
    for ($i = 0; $i < count($topResults);$i++){
        if ($row['Score'] > $topResults[$i][2]){
            for ($j = count($topResults); $j > $i; $j--){
                $topResults[$j] = $topResults[$j-1];
            }
            $topResults[$i] = array($row['mid'], 'm', $row['Score'] - $movieWeight);
            break;
        }
    }
    $movieFound = 1;
}

//.... add the other content types here following the movie title example

for ($i = 0; $i < count($topResults); $i++){
    if ($topResults[$i][1] == 'm'){
        if ($countMovies < $limit) {
            $movieTitleDivText .= str_replace('\'','&#39;',createPersonMovieImageLink($topResults[$i][0]));
            $countMovies++;
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...