Comment améliorer les recherches dans la base de données avec la recherche en texte intégral dans MySQL 5.6 sous Ubuntu 16.04

introduction

La recherche en texte intégral, ou FTS, est une technique utilisée par les moteurs de recherche pour trouver des résultats dans une base de données. Vous pouvez l’utiliser pour optimiser les résultats de recherche sur des sites Web tels que des magasins, des moteurs de recherche, des journaux, etc.

Plus spécifiquement, FTS récupère les documents qui ne correspondent pas parfaitement aux critères de recherche. Documents sont des entités de base de données contenant des données textuelles. Cela signifie que lorsqu’un utilisateur recherche «chats et chiens», par exemple, une application appuyée par FTS peut renvoyer des résultats contenant les mots séparément (uniquement «chats» ou «chiens»), dans un ordre différent. (“Chiens et chats”), ou contiennent des variantes des mots (“chat” ou “chien”). Cela donne aux applications un avantage à deviner ce que l’utilisateur veut dire et à obtenir plus rapidement des résultats plus pertinents.

Techniquement, les systèmes de gestion de base de données (SGBD) tels que MySQL autorisent généralement les recherches de texte partielles à l’aide de clauses + LIKE +. Cependant, ces demandes ont tendance à sous-performer sur des jeux de données volumineux. Ils sont également limités à faire correspondre les entrées de l’utilisateur avec précision, ce qui signifie qu’une requête peut ne produire aucun résultat, même s’il existe des documents contenant des informations pertinentes.

En utilisant FTS, vous pouvez créer un moteur de recherche de texte plus puissant sans introduire de dépendances supplémentaires sur des outils plus avancés. Dans ce didacticiel, vous utiliserez MySQL 5.6 pour interroger une base de données à l’aide de la recherche en texte intégral, puis quantifier les résultats en fonction de leur pertinence pour l’entrée de recherche et afficher uniquement les meilleures correspondances.

Conditions préalables

Avant de commencer ce tutoriel, vous aurez besoin de:

Étape 1 - Création des données de test

Pour essayer la recherche en texte intégral, nous avons besoin de certaines données. Dans cette étape, nous allons créer une base de données appelée + testdb + avec une table appelée + news +, que nous renseignerons à l’aide de quelques exemples de données représentant des articles provenant d’un site agrégateur de nouvelles fictif.

Tout d’abord, accédez à la console MySQL. Vous serez invité à entrer le mot de passe * root * que vous avez défini lors de l’installation de MySQL.

mysql -u root -p

Une fois que vous êtes connecté, votre invite deviendra + mysql> +.

Ensuite, créez une nouvelle base de données appelée + testdb +. Cette base de données contiendra les données de test.

CREATE DATABASE testdb;

Basculez vers l’utilisation de la base de données + testdb + par défaut afin de ne pas avoir à spécifier le nom de la base de données pour créer ou mettre à jour des éléments qu’elle contient.

USE testdb;

Ensuite, créez une table dans la base de données appelée + news + avec des colonnes pour un exemple d’agrégateur de news.

CREATE TABLE news (
  id INT NOT NULL AUTO_INCREMENT,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  author TEXT NOT NULL,

  PRIMARY KEY (id)
);

Passons en revue ce que cette commande fait:

  • + CREATE TABLE + est une commande SQL qui crée une table, similaire à de nombreuses autres bases de données.

  • + news + est le nom de la table.

  • + title,` + content` et + author sont des colonnes textuelles de longueur illimitée.

  • + NOT NULL + est une déclaration utilisée pour marquer les colonnes qui ne peuvent pas avoir null values (bien qu’elles puissent contenir chaînes vides).

  • + id + est l’index principal de la table avec le type spécial + AUTO_INCREMENT +, qui remplit automatiquement le champ ID avec le prochain identifiant disponible.

Ajoutez maintenant quelques exemples de données à la table.

INSERT INTO news (id, title, content, author) VALUES
   (1, 'Pacific Northwest high-speed rail line', 'Currently there are only a few options for traveling the 140 miles between Seattle and Vancouver and none of them are ideal.', 'Greg'),
   (2, 'Hitting the beach was voted the best part of life in the region', 'Exploring tracks and trails was second most popular, followed by visiting the shops and then traveling to local parks.', 'Ethan'),
   (3, 'Machine Learning from scratch', 'Bare bones implementations of some of the foundational models and algorithms.', 'Jo');

Passons en revue ce que cette commande fait:

  • + INSERT + insère des données.

  • + INTO + spécifie où les données doivent être insérées. Dans ce cas, il s’agit de la table + news +.

  • + (id, titre, contenu, auteur) VALUES + spécifie les colonnes dans lesquelles les valeurs de données de chaque entrée doivent être stockées.

  • Les trois dernières lignes sont les trois lignes de données que nous ajoutons à la table. Chacun contient un exemple d’article pour un site Web d’information avec un + titre +, un + contenu + et le nom de + l’auteur + '.

Chaque entrée possède également un unique identificateur + id + qui est automatiquement entré dans l’index de la base de données. Database index est une structure de données qui améliore les performances des opérations de récupération de données. Cet index est stocké séparément des données principales. Il met à jour toutes les modifications apportées au contenu de la table au prix d’écritures supplémentaires et d’un espace de stockage comparativement réduit. Sa petite taille et sa structure de données sur mesure permettent aux index de fonctionner beaucoup plus efficacement que d’utiliser l’espace table principal pour la sélection de requêtes.

Maintenant que nous avons quelques données, nous pouvons commencer à écrire des requêtes pour rechercher ces données en utilisant FTS.

Étape 2 - Création d’un index FTS et utilisation des fonctions FTS

Faisons un index pour les colonnes de texte que nous avons afin que nous puissions utiliser FTS.

Pour ce faire, nous utiliserons une commande exclusive à MySQL appelée + FULLTEXT +. Cette commande indique à MySQL de mettre tous les champs que nous voulons pouvoir rechercher avec FTS dans un index interne.

ALTER TABLE news ADD FULLTEXT (title, content, author);

Cela fonctionne en combinant toutes les colonnes de texte et en les désinfectant (par exemple, enlever la ponctuation et mettre les lettres majuscules en minuscules). Maintenant que cet index est créé, il sera mis à jour par toute requête SQL modifiant le contenu de la table source.

Ensuite, essayez d’effectuer une recherche en texte intégral pour «Seattle beach» à l’aide de la fonction + MATCH () AGAINST () +.

SELECT * FROM news WHERE MATCH (title,content,author) AGAINST ('' IN NATURAL LANGUAGE MODE)\G

La partie + MATCH () + de la commande spécifie quel ensemble de colonnes est indexé à l’aide de FTS; il doit correspondre à la liste de colonnes que vous avez utilisée pour créer l’index. La partie + AGAINST () + spécifie le mot pour lequel nous effectuons une recherche en texte intégral, qui est «Seattle beach» dans cet exemple.

«+ IN NATURAL LANGUAGE MODE +» signifie que les mots de recherche sont fournis directement à partir de la saisie de l’utilisateur, sans aucun traitement préalable. MySQL utilise le mode de langage naturel par défaut, vous n’avez donc pas à le spécifier explicitement.

Le signe + \ G + situé à la fin de la requête ci-dessus fait que chaque colonne de la sortie est imprimée sur une nouvelle ligne. Cela peut rendre les résultats longs un peu plus faciles à lire. Le résultat de la commande ci-dessus ressemblera à ceci:

Output*************************** 1. row ***************************
    id: 1
 title: Pacific Northwest high-speed rail line
content: Currently there are only a few options for traveling the 140 miles between  and Vancouver and none of them are ideal.
author: Greg
*************************** 2. row ***************************
    id: 2
 title: Hitting the  was voted the best part of life in the region
content: Exploring tracks and trails was second most popular, followed by visiting the shops and then traveling to local parks.
author: Ethan
2 rows in set (0.00 sec)

Aucune entrée ne contenait l’expression «Seattle beach», mais comme nous avons utilisé la recherche en texte intégral, nous avons toujours deux résultats: la première ligne, qui ne contient que le mot «Seattle», et la deuxième ligne, qui ne contient que le mot "plage". Vous pouvez essayer des recherches supplémentaires en modifiant les mots-clés pour afficher les résultats.

Maintenant que vous pouvez utiliser les fonctions FTS dans les requêtes SQL pour trouver les lignes pertinentes pour une entrée de recherche, vous pouvez rendre ces résultats plus pertinents.

Étape 3 - Raffinage des résultats FTS

Deux techniques peuvent aider à rendre les résultats de recherche de texte intégral plus pertinents. L’une filtre les résultats en fonction de leur pertinence, l’autre utilise + IN BOOLEAN + pour exclure des mots particuliers des résultats et spécifier une distance maximale entre les termes de recherche.

Utilisation du score de pertinence

Le score de pertinence d’un résultat quantifie la qualité d’une correspondance pour le terme recherché, où 0 n’est pas pertinent du tout. Le score de pertinence est basé sur un certain nombre de facteurs, y compris la fréquence à laquelle le terme est trouvé dans un document spécifique et le nombre de documents contenant le terme. La documentation de recherche en texte intégral de MySQL explique en détail le calcul de ce nombre.

Obtenez les scores de pertinence pour chaque ligne en fonction de la requête «se rendre dans les parcs».

SELECT id, MATCH (title,content,author) AGAINST ('') as score FROM news;

La partie + as score + de cette commande nomme la deuxième colonne de la sortie comme + score +. Sinon, il serait étiqueté avec la commande utilisée pour le remplir, qui dans ce cas était + MATCH (titre, contenu, auteur) AGAINST ('voyager dans les parcs') +.

Le résultat ressemblera à ceci:

Output+----+----------------------+
| id | score                |
+----+----------------------+
|  1 | 0.031008131802082062 |
|  2 |  0.25865283608436584 |
|  2 |  0                    |
+----+----------------------+
3 rows in set (0.00 sec)

La troisième ligne a un score de pertinence de 0 car aucun des termes de la recherche n’y apparaît. La première rangée contient le mot «voyager», mais pas «vers» ou «les parcs», et a un score de pertinence très faible de «+ 0,03 ». La deuxième ligne, qui contient tous les mots, a le score de pertinence le plus élevé, soit ` 0,25 +`.

Vous pouvez utiliser ces scores pour renvoyer d’abord les résultats les plus pertinents, ou pour ne renvoyer que les résultats qui dépassent une certaine plage de pertinence. Les scores de pertinence varient selon les ensembles de données. Le choix d’un point de coupure nécessite un réglage manuel.

La commande suivante exécute la même requête, mais ajoute deux choses:

  • Il affiche uniquement les lignes avec des scores de pertinence non nuls en ajoutant + WHERE MATCH (titre, contenu, auteur) AGAINST ('')> 0 +

  • Il trie les résultats par pertinence en ajoutant + ORDER BY score DESC +

SELECT id, MATCH (title,content,author) AGAINST ('') as score FROM news WHERE MATCH (title,content,author) AGAINST ('') > 0 ORDER BY score DESC;

Vous devez répéter la fonction + MATCH () AGAINST () + dans la clause + WHERE + en raison des restrictions SQL sur ce qui peut être inclus dans cette clause.

La sortie ressemblera à ceci:

Output+----+----------------------+
| id | score                |
+----+----------------------+
|  2 |  0.25865283608436584 |
|  1 | 0.031008131802082062 |
+----+----------------------+
2 rows in set (0.01 sec)

Le résultat le plus pertinent, la ligne 2, est affiché en premier, suivi de la ligne 1, moins pertinente. La rangée 3 n’est pas affichée du tout car son score de pertinence est 0.

Vous pouvez modifier les seuils pour continuer à affiner vos résultats. Par exemple, si vous utilisez + 0.1 + au lieu de + 0 + comme valeur limite, seule la ligne 2 sera renvoyée.

Utiliser IN BOOLEAN

À l’étape 2, vous avez utilisé le mode par défaut + IN NATURAL LANGUAGE lors de la spécification d’un terme de requête. Il existe un autre mode, + IN BOOLEAN +, qui vous permet d’exclure des mots particuliers d’une recherche, de définir une plage de distance entre les mots de l’entrée, et plus encore.

Pour omettre un terme d’une requête, utilisez l’opérateur moins avec + IN BOOLEAN. La commande suivante renverra les résultats contenant le mot «travelling» mais ne contient pas le mot «Seattle».

SELECT * FROM news WHERE MATCH (title,content,author) AGAINST ()\G

Les résultats ne montreront que la ligne 2:

Output*************************** 1. row ***************************
    id: 2
 title: Hitting the beach was voted the best part of life in the region
content: Exploring tracks and trails was second most popular, followed by visiting the shops and then traveling to local parks.
author: Ethan
1 row in set (0.01 sec)

Cela fonctionne parce que l’opérateur moins indique au DMS de marquer tout document avec les mots exclus avec un score de pertinence de 0. Seuls les résultats avec un score de pertinence non nul sont affichés dans ce mode.

Vous pouvez également utiliser + IN BOOLEAN MODE + pour spécifier la distance maximale entre les termes de recherche. Cette distance est mesurée en mots et, surtout, inclut les termes de recherche. Par exemple, l’expression «chats et chiens» a une distance de 3.

La commande suivante retourne des résultats dans lesquels les mots «travelling» et «miles» apparaissent avec 2 mots au maximum.

SELECT * FROM news WHERE MATCH (title,content,author) AGAINST ()\G

Vous verrez un résultat, qui correspond à "+ parcourant les 140 km" de la ligne 2, "+ contenu".

Output*************************** 1. row ***************************
    id: 1
 title: Pacific Northwest high-speed rail line
content: Currently there are only a few options for traveling the 140 miles between Seattle and Vancouver and none of them are ideal.
author: Greg
1 row in set (0.00 sec)

Si vous modifiez le signe "+ @ 4 " en " @ 3 +" dans la commande d’origine, vous ne verrez aucun résultat.

Il peut être utile de limiter les résultats de recherche en fonction de la distance entre les termes de recherche lorsque vous recherchez des documents de très grande taille avec des vocabulaires variés. Plus l’écart entre les termes de la requête est petit, plus les résultats seront précis, bien que l’ajustement de la distance dépende de l’ensemble des documents avec lesquels vous travaillez. Par exemple, un ensemble d’articles scientifiques peut bien fonctionner avec un petit espace de 3 mots, mais la recherche de messages de forum peut être plus efficace avec un espace d’au moins 8, selon l’ampleur ou la fin des résultats.

Conclusion

Dans ce guide, vous avez utilisé la fonction de recherche en texte intégral de MySQL. Vous avez créé un index lors de la création d’un schéma de base de données pour votre base de documents, puis avez utilisé des opérateurs spéciaux pour rechercher les résultats les plus pertinents lors d’une requête.

Si vous souhaitez explorer davantage les fonctionnalités FTS de MySQL, vous pouvez consulter la documentation officielle MySQL 5.6.