2010-07-02 9 views
2

J'essaie de joindre plusieurs tables et d'effectuer une recherche en texte intégral sur celles-ci.Recherche plein texte MySQL sur plusieurs tables avec différents champs

La plupart des tables ne sont pas liées mais ont des champs similaires.

J'ai eu les recherches fulltext fonctionnelles mais je dois être capable de créer des liens à partir des résultats qui est la prochaine étape mais je ne dilue pas k cela fonctionnera parce que je n'ai pas eu assez de champs pour obtenir assez d'info .

Fondamentalement, je veux rechercher le titre et le contenu de chaque table, mais je veux aussi rechercher mes tables de forum qui sont des sujets et des messages. Les tables de rubriques et de messages sont liées.

Cette requête va faire l'affaire sans interroger les tables du forum car il faut que je puisse rechercher ces tables.

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 

Je devrais être en mesure de créer des liens pour les tables qui ont des noms de champ commom tels que events.php? Id = 1 obtenir l'identifiant du dossier, mais comment pourrais-je faire pour les sujets des tables et des messages topic.php? boardid = 1 & topic = 2?

Voici ma structure de table CREATE TABLE articles ( id int (4) NOT auto_increment NULL, title varchar (70) NOT NULL default '', content texte NOT NULL, clé primaire (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`) 
    ); 

Voici comment je reçois actuellement tous les dossiers, mais il n'y a pas moyen d'ajouter des champs supplémentaires pour les tables sujets et messages à l'aide d'un 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 

Répondre

3

je suis tombé sur cette question la construction d'une recherche sur un site Web avec plusieurs types de contenu (base de données de films). Je voulais que l'utilisateur puisse faire une recherche et trouver un acteur, un film ou un nom de personnage. Au lieu d'essayer d'obtenir une grosse instruction SQL, j'ai fait une correspondance pour chaque type de contenu (movie_title, movie_plot, actor_name, character_name, etc.) et j'ai bloqué l'identifiant de la ligne, le type de contenu et le score du match dans un tableau multidimensionnel. Je limiterais généralement chaque type de contenu aux 50 meilleurs résultats.

J'ai ensuite été en mesure de trier la matrice en fonction du score. Ensuite, j'utiliserais l'identifiant et le type de contenu pour rechercher les informations dont j'avais besoin pour chaque résultat.

EDIT (code ajouter)

Avertissement: Ceci est l'ancien code, et il y a probablement des moyens plus efficaces de le faire

$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++; 
     } 
} 
+0

Avez-vous un code d'exemple de la façon dont vous l'avez fait? Avez-vous utilisé plusieurs requêtes? – AdRock

+0

auriez-vous plusieurs requêtes pour chaque table puis ajouter au tableau? – AdRock

+0

Je voudrais avoir au moins 1 requête pour chaque table, les résultats de chaque étant mis dans un tableau. –