Mysql
 sql >> Base de données >  >> RDS >> Mysql

comment implémenter la recherche de 2 données de table différentes ?

Voici quelques "règles du jeu" que vous devez garder à l'esprit pour résoudre ce problème. Vous les connaissez probablement déjà, mais les énoncer clairement peut aider à confirmer pour d'autres lecteurs.

  • Tous les index de MySQL ne peuvent référencer que des colonnes dans une seule table de base. Vous ne pouvez pas créer un index de texte intégral qui indexe plusieurs tables.
  • Vous ne pouvez pas définir d'index pour les vues, uniquement les tables de base.
  • Un MATCH() la requête sur un index de texte intégral doit correspondre à toutes les colonnes de l'index de texte intégral, dans l'ordre déclaré dans l'index.

Je créerais une troisième table pour stocker le contenu que vous souhaitez indexer. Pas besoin de stocker ce contenu de manière redondante -- stockez-le uniquement dans la troisième table. Cela emprunte un concept de "superclasse commune" à la conception orientée objet (dans la mesure où nous pouvons l'appliquer à la conception de SGBDR).

CREATE TABLE Searchable (
  `id` SERIAL PRIMARY KEY,
  `title` varchar(100) default NULL,
  `description` text,
  `keywords` text,
  `url` varchar(255) default '',
  FULLTEXT KEY `TitleDescFullText` (`keywords`,`title`,`description`,`url`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `shopitems` (
  `id` INT UNSIGNED NOT NULL,
  `ShopID` INT UNSIGNED NOT NULL,
  `ImageID` INT UNSIGNED NOT NULL,
  `pricing` varchar(45) NOT NULL,
  `datetime_created` datetime NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`id`) REFERENCES Searchable (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `shops` (
  `id` INT UNSIGNED NOT NULL,
  `owner_id` varchar(255) default NULL,
  `datetime_created` datetime default NULL,
  `created_by` varchar(255) default NULL,
  `datetime_modified` datetime default NULL,
  `modified_by` varchar(255) default NULL,
  `overall_rating_avg` decimal(4,2) default '0.00',
  PRIMARY KEY (`id`),
  FOREIGN KEY (`id`) REFERENCES Searchable (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Notez que la seule table avec une clé d'auto-incrémentation est désormais Searchable . Les tables shops et shopitems utilisez une clé avec un type de données compatible, mais pas d'auto-incrémentation. Vous devez donc créer une ligne dans Searchable pour générer l'id valeur, avant de pouvoir créer la ligne correspondante dans l'un ou l'autre des shops ou shopitems .

J'ai ajouté FOREIGN KEY déclarations à des fins d'illustration, même si MyISAM ignorera silencieusement ces contraintes (et vous savez déjà que vous devez utiliser MyISAM pour prendre en charge l'indexation de texte intégral).

Vous pouvez maintenant rechercher le contenu textuel des deux shops et shopitems en une seule requête, en utilisant un seul index fulltext :

SELECT S.*, sh.*, si.*,
  MATCH(keywords, title, description, url) AGAINST('dummy') As score
FROM Searchable S
LEFT OUTER JOIN shops sh ON (S.id = sh.id)
LEFT OUTER JOIN shopitems si ON (S.id = si.id)
WHERE MATCH(keywords, title, description, url) AGAINST('dummy')
ORDER BY score DESC;

Bien sûr, pour une ligne donnée dans Searchable une seule table doit correspondre, soit boutiques, soit articles de boutique, et ces tables ont des colonnes différentes. Donc soit sh.* ou si.* sera NULL dans le résultat. C'est à vous de formater la sortie dans votre application.

Quelques autres réponses ont suggéré d'utiliser Sphinx Search . Il s'agit d'une autre technologie qui complète MySQL et ajoute une capacité de recherche en texte intégral plus sophistiquée. Il a d'excellentes performances pour les requêtes, de sorte que certaines personnes en ont été assez enchantées.

Mais la création d'index et en particulier l'ajout à un index de manière incrémentielle coûte cher. En fait, la mise à jour d'un index Sphinx Search est si coûteuse que la solution recommandée consiste à créer un index pour les données archivées plus anciennes et un autre index plus petit pour les données récentes qui sont plus susceptibles d'être mises à jour. Ensuite, chaque recherche doit exécuter deux requêtes, sur les deux index distincts. Et si vos données ne se prêtent pas naturellement au modèle de données plus anciennes qui ne changent pas, vous ne pourrez peut-être pas profiter de cette astuce de toute façon.

Concernant votre commentaire :voici un extrait de la documentation Sphinx Search à propos des mises à jour en direct d'un index :

L'idée est que, puisqu'il est coûteux de mettre à jour un index Sphinx Search, leur solution consiste à rendre l'index que vous mettez à jour aussi petit que possible. Ainsi, seuls les messages de forum les plus récents (dans leur exemple), alors que l'historique plus large des messages de forum archivés ne changent jamais, vous créez donc un deuxième index plus grand pour cette collection une fois. Bien sûr, si vous voulez faire une recherche, vous devez interroger les deux index.

Périodiquement, disons une fois par semaine, les messages "récents" du forum deviendraient considérés comme "archivés" et vous devriez fusionner l'index actuel des messages récents avec l'index archivé, et recommencer l'index plus petit. Ils soulignent que la fusion de deux index Sphinx Search est plus efficace que la réindexation après une mise à jour des données.

Mais ce que je veux dire, c'est que tous les ensembles de données ne tombent pas naturellement dans le schéma d'avoir un ensemble de données archivé qui ne change jamais, par rapport aux données récentes qui sont mises à jour fréquemment.

Prenez votre base de données par exemple :vous avez des boutiques et des articles de boutique. Comment pouvez-vous les séparer en lignes qui ne changent jamais, par rapport aux nouvelles lignes ? Tous les magasins ou produits du catalogue doivent être autorisés à mettre à jour leur description. Mais comme cela nécessiterait de reconstruire l'intégralité de l'index Sphinx Search à chaque fois que vous apportez une modification, cela devient une opération très coûteuse. Vous pourriez peut-être mettre les modifications en file d'attente et les appliquer dans un lot, en reconstruisant l'index une fois par semaine. Mais essayez d'expliquer aux vendeurs de la boutique pourquoi une modification mineure de la description de leur boutique ne prendra effet que dimanche soir.