Construire un moteur de recherche avec MySQL
Lorsqu'un site prend de l'importance en terme de contenu et que le nombres de pages Web ne cessent d'augmenter, la nécessité de fournit un moteur de recherche pour le site Web devient primordial afin que l'internaute puisse trouver ce qu'il cherche vraiment. La première idée venant à l'esprit c'est d'utiliser directement la base de données MySQL pour y parvenir, toutefois, une recherche efficace n'est pas assez banal pour qu'on utilise une commande magique et que la base de données nous sortes les résultats les plus pertinents.
MySQL n'est pas un moteur de recherche
La base de données MySQL est une base de données relationnelle et donc pas un moteur de recherche. Bien qu'il fournit des outils pour effectuer des recherches dans les données qu'il contient, il est souvent préférable d'intégrer un vrai moteur de recherche si vous recherchez une solution complète. Voici les moteurs de recherches les plus populaires :
Nom | Commentaires |
---|---|
Elasticsearch | OpenSource, serveur basé sur Lucene |
Endeca | Propriété d'Oracle |
Lucene | OpenSource |
Sphinx | OpenSource |
Solr | OpenSource, serveur basé sur Lucene |
Recherche Texte-plein (Full-text)
Le SQL de la base de données MySQL permet d'effectuer une recherche des textes en incluant la clause «WHERE» des «champ LIKE '%mot%'» ou «champ REGEXP '.*mot'» mais ceux-ci demeure relativement limité. De plus, il n'exploite pas les «INDEX» contenu dans la table, lequel rend le résultat de la recherche lent à obtenir. Ainsi, plus, il y a aura de contenu, plus le résultat sera long à obtenir.
Pour effectuer une recherche texte-plein (Full-Text), la technique que devrait utilisé serait plutôt d'ajouter un index FULLTEXT au champ dans lequel vous souhaitez effectuer une recherche et ensuite utiliser une requête comme ceci «MATCH(champ) AGAINST('mot')». Ainsi, vous auriez donc une requête comme ceci :
SELECT * FROM table WHERE MATCH(champ) AGAINST('mot');
L'avantage de la fonction «MATCH», contrairement à une fonction de recherche classique, tient du fait, qu'elle retourne un poids de pertinence. Ainsi, il sera possible de sortir des sortir les résultat les pertinents en premier avec une requête comme ceci :
SELECT * FROM table WHERE MATCH(champ) AGAINST('mot') ORDER BY MATCH(champ) AGAINST('mot') DESC;
Le mode Booléen
Par défaut, la fonction «MATCH» applique une recherche «IN NATURAL LANGUAGE MODE», soit une recherche par mode naturel du langage, où chaque mot de votre clause «AGAINST» sera appliqué à votre champ. Ce mode de recherche n'est malheureusement pas toujours pertinent et il ne tient pas compte du contexte dans lequel le mot se trouve. Ainsi, il existe le mode «IN BOOLEAN MODE» lequel permet des possibilités telles que l'exclusion de certain mot ou de calculer un poids plus égale pour tous les mots.
Voici la liste des opérateurs reconnus par le mode «BOOLEAN» de la recherche texte-plein (Full-text) :
Opérateur | Description |
---|---|
(pas d'opérateur) | Lorsqu'il n'y pas d'opérateur, il retour un poids de pertinence le plus élevé lorsqu'il correspond. |
+ | Cet opérateur permet d'indiquer que le mot doit être présent dans le texte. |
- | Cet opérateur permet d'indiquer que le mot ne doit pas être présent dans le texte. |
@distance | Cet opérateur permet d'indiquer que le mots recherchés devraient apparaître dans le texte à une certaine distance les uns des autres. |
> < | Cet opérateur permet d'augmenter ou de diminuer l'importance d'un mot dans la recherche. |
( ) | Cet opérateur permet de regrouper des mots en sous-expressions. |
~ | Cet opérateur permet de remplacer le poids de pertinence par le soustraction du mot. |
* | Cet opérateur permet d'indiquer un caractère pouvant remplacer tous les débuts de mot. |
" | Cet opérateur permet d'indiquer, que tous contenu situé à l'intérieur de 2 guillemets doit être recherché de façon exacte et sans interprétation. |
Ajustement
La recherche à l'aide de la fonction «MATCH» est merveilleuse par sa simplicité mais les valeurs des variables de configuration par défaut ne sont pas nécessairement ajustés à vos besoins. Ainsi, par exemple ft_min_word_len et ft_max_word_len indiquant la longueur minimum et maximum d'un mot. Par défaut, la longueur minimum d'un mot est de 4 lettres, et dans de nombreuses situations, lorsque vous ferez des tests, vous constaterez que 3 seraient une valeurs plus appropriés.
Remarques
- Si vous combiner plusieurs tables, éviter autant que possible d'effectuer l'assemblage des données dans le langage de programmation parent, comme PHP, et indiquez plutôt à la base de données quoi retourner exactement. Sinon, l'accumulation de niveau risque de provoquer une surcharge sur votre langage de programmation parent.
- Les fonctionnalités de la recherche de MySQL ne tient pas compte des fautes d'orthographes ou encore de l'écriture du mot en se basant sur le son. Ainsi, il existe bien une fonction appeler «SOUNDEX», mais celle-ci révèle s'est limite dans un contexte de recherche.
Exemple
L'exemple suivant permet de rechercher dans la table «cdmarticle», en indiquant que le mot «test» est facultatif mais que «fork» est obligatoire :
SELECT * FROM cdmarticle WHERE MATCH (contentText ) AGAINST ( '+fork test' IN BOOLEAN MODE )