Comment ajouter une recherche à votre application : des filtres simples à la recherche plein texte
Pour ajouter une recherche à votre application, commencez par la solution la plus simple qui fonctionne : une zone de recherche qui appelle une route serveur, laquelle filtre les lignes de votre base de données en comparant la requête à quelques colonnes, avec des filtres pour des éléments comme la catégorie ou le prix. Lorsque cela ne suffit plus — vous avez besoin d'un classement par pertinence, de la racinisation des mots ou de nombreux enregistrements —, passez à la recherche plein texte de votre base de données, et ne vous tournez vers un moteur de recherche hébergé que si vous avez besoin d'une forte tolérance aux fautes de frappe ou de résultats instantanés sur de très grandes données. Quel que soit votre choix, la recherche doit respecter les permissions : les utilisateurs ne doivent jamais trouver des enregistrements auxquels ils n'ont pas le droit d'accéder.
Ce que « recherche » signifie pour votre application
La recherche recouvre plusieurs choses différentes, et la plupart des applications en ont besoin de plusieurs :
- Recherche par mots-clés : une zone de texte — « trouver les annonces qui mentionnent “jardin” ».
- Filtres : des choix structurés — catégorie, ville, fourchette de prix, date, statut.
- Tri : du plus récent au moins cher, ou du plus pertinent.
- Saisie semi-automatique : des suggestions pendant la frappe.
- Tolérance aux fautes de frappe : « restuarant » trouve encore « restaurant ».
Pour un annuaire, un site d'emploi ou une boutique, les filtres comptent souvent davantage que la zone de texte. Décidez lesquels de ces éléments vous sont réellement utiles avant de choisir un outil.
Vos options
| Approche | Fonctionnement | Idéal pour | Limites |
|---|---|---|---|
| Filtrer dans le navigateur | Charger la liste, la filtrer en JavaScript | Petites listes publiques (quelques centaines d'éléments) | Envoie toutes les données à chaque visiteur ; lent avec de grandes listes |
| Correspondance de motif dans la base | Requête serveur du type « le nom contient le texte », insensible à la casse | Petites et moyennes applications, outils d'administration | Pas de classement ; peut ralentir sur de grandes tables ; pas de racinisation |
| Recherche plein texte dans la base | Postgres indexe les mots et classe les résultats | La plupart des applications riches en contenu | Faible face aux fautes de frappe sans correspondance floue |
| Correspondance floue (trigrammes) | Postgres compare des suites de caractères pour évaluer la similarité | Noms, champs courts, tolérance aux fautes | Nécessite une extension et un index ; le réglage demande de l'attention |
| Moteur de recherche hébergé | Un service séparé indexe vos données (Algolia, Meilisearch, Typesense, Elasticsearch et d'autres) | Grands catalogues, recherche instantanée, forte tolérance aux fautes | Un service de plus à synchroniser, à payer et à sécuriser |
Si vos données se trouvent déjà dans Postgres, sa recherche plein texte intégrée constitue un excellent compromis. Elle découpe le texte en mots, les réduit à leurs racines (si bien que « courir » correspond à « cour »), ignore les mots courants et peut classer les résultats selon leur degré de correspondance. Avec le bon index, elle reste rapide sur de grandes tables.
Exemples de requêtes
Un démarrage simple :
Ajoute une zone de recherche et des filtres à la page des annonces. La recherche doit comparer la requête au titre et à la description, sans tenir compte de la casse. Filtres : catégorie (liste déroulante), ville (liste déroulante) et prix maximum. Effectue la recherche sur le serveur avec une route d'API paginée, 20 résultats par page. Conserve la recherche et les filtres dans l'URL pour que les résultats puissent être partagés et que le bouton précédent fonctionne. Affiche un message convivial lorsque rien ne correspond.
Passage à la recherche plein texte :
Passe la recherche des annonces à la recherche plein texte de Postgres sur le titre (pondéré plus haut) et la description. Ajoute l'index adéquat, classe les résultats par pertinence, et conserve les filtres et la pagination existants. Ne modifie aucune donnée existante.
Ajouter la tolérance aux fautes de frappe pour les noms :
Ajoute une correspondance floue sur le nom de l'entreprise pour que de petites fautes de frappe donnent encore des résultats. Utilise la similarité par trigrammes si elle est disponible, avec un index, et reviens à la recherche actuelle sinon.
Étape par étape
- Listez ce que les gens recherchent. Quels champs (titre, description, étiquettes, nom) ? Quels filtres ? Interrogez quelques utilisateurs réels si possible.
- Commencez côté serveur. Ajoutez une route d'API qui reçoit la requête et les filtres, et renvoie une page de résultats. Ne chargez pas tout dans le navigateur.
- Appliquez les permissions dans la requête. Si les utilisateurs ne voient que leurs propres enregistrements, ou seulement ceux qui sont publiés, cette condition doit figurer dans la même requête que la recherche.
- Ajoutez la pagination dès le départ : numéros de page ou « Charger plus ».
- Placez l'état de la recherche dans l'URL (par exemple
?q=jardin&city=leeds). Les liens partageables, le bouton précédent qui fonctionne et les moteurs de recherche peuvent explorer les pages filtrées si vous le souhaitez. - Temporisez la recherche pendant la frappe. Attendez quelques centaines de millisecondes après la fin de la saisie avant d'interroger, pour ne pas envoyer une requête à chaque touche.
- Ajoutez des index une fois que vous savez quelles colonnes vous filtrez et recherchez.
- Évoluez vers la recherche plein texte, puis la correspondance floue, puis un moteur hébergé — uniquement lorsque l'étape plus simple échoue auprès de vrais utilisateurs.
- Testez avec des données réalistes : des centaines ou des milliers de lignes, des caractères inhabituels, des requêtes vides, des requêtes très longues, d'autres langues si vous les prenez en charge.
Erreurs courantes
- Charger toute la table dans le navigateur. C'est acceptable pour 50 éléments, pénible pour 50 000, et cela expose chaque enregistrement, y compris ceux que l'utilisateur ne devrait pas voir.
- Une recherche qui ignore les permissions. La recherche est une fuite fréquente : un enregistrement privé ou un brouillon apparaît parce que la requête a oublié la condition « seulement les miens » ou « seulement les publiés ».
- Construire du SQL à partir de données brutes saisies par l'utilisateur. Utilisez toujours des requêtes paramétrées. Un créateur d'applications par IA le fait normalement, mais vérifiez si vous voyez des chaînes assemblées bout à bout.
- Pas de message d'état vide. Un « Aucun résultat » accompagné d'une suggestion (effacer les filtres, vérifier l'orthographe) évite que les gens ne partent.
- Aucun index. La recherche semble correcte avec des données de test, puis ralentit à mesure que les vraies données grossissent.
- Passer directement à un service de recherche. Vous devez alors garder une seconde copie de vos données synchronisée, gérer les suppressions et sécuriser un autre jeu de clés — souvent sans gain visible.
- Oublier le mobile. Les filtres doivent tenir sur un téléphone ; un tiroir de filtres ou un panneau repliable fonctionne en général mieux qu'une barre latérale.
Liste de contrôle
- Vous savez quels champs sont recherchés et quels filtres existent
- La recherche s'exécute sur le serveur et renvoie des résultats paginés
- La requête applique les mêmes permissions que le reste de l'application
- La saisie de l'utilisateur est transmise comme paramètres, jamais assemblée dans du SQL
- L'état de la recherche est stocké dans l'URL
- La saisie est temporisée (debounce)
- Les colonnes recherchées et filtrées sont indexées
- Les états vide, sans résultat et d'erreur sont clairs
- Testé avec des volumes de données réalistes et des saisies désordonnées
Ajouter une recherche avec Mythex
Dans une application créée sur Mythex, les données se trouvent généralement dans la base Postgres du projet ; vous pouvez donc commencer avec les requêtes ci-dessus : d'abord la correspondance de motifs, puis la recherche plein texte de Postgres lorsque vous avez besoin de classement. Si vous voulez un moteur de recherche hébergé, apportez votre propre compte et votre clé, stockez-la comme secret du projet, et demandez à l'agent de l'indexer et de l'interroger depuis le serveur, comme décrit dans Intégrer n'importe quelle API.
La recherche est au cœur de nombreuses applications : voir comment créer un site annuaire, comment créer un site d'offres d'emploi et comment créer une marketplace pour comprendre sa place dans le reste du produit.
Questions
Quelle est la façon la plus simple d'ajouter une recherche à une application ?
Si vos données sont dans une base de données, une route serveur qui filtre les lignes avec une correspondance insensible à la casse sur quelques colonnes est le point de départ le plus simple. Pour une petite liste déjà chargée dans le navigateur, filtrer directement dans le navigateur est encore plus simple.
Ai-je besoin d'Algolia ou d'Elasticsearch pour la recherche ?
En général, pas au début. La recherche plein texte de Postgres gère très bien la correspondance des mots, le classement et des milliers à des millions de lignes. Un moteur de recherche hébergé vaut la peine lorsque vous avez besoin d'une forte tolérance aux fautes de frappe, de résultats instantanés pendant la saisie sur de grandes masses de données, ou d'un réglage avancé de la pertinence.
Pourquoi ma recherche ne trouve-t-elle pas de résultats avec des fautes de frappe ?
Une correspondance de base et la recherche plein texte standard cherchent les mots tels qu'ils sont saisis (ou leurs racines), donc une faute d'orthographe ne donne rien. Il faut une correspondance floue, comme la similarité par trigrammes dans Postgres, ou un moteur de recherche tolérant aux fautes de frappe.
La recherche doit-elle s'exécuter dans le navigateur ou sur le serveur ?
Sur le serveur, pour tout ce qui dépasse une petite liste publique. La recherche côté serveur passe à l'échelle, respecte les permissions et n'envoie pas l'ensemble de vos données à chaque visiteur.