Sommaire
Bonjour bonjour 😁,
Cette semaine, on attaque un gros sujet, cet article fait suite à « Pourquoi MYSQL n'est-il pas un moteur de recherche ? ».
Dans ce dernier, je vous parlais d'Elasticsearch, un moteur de base de données indexée populaire et qui fait bien le travail.
Cette semaine, on va parler de Typesense, si vous passez de temps en temps sur ce blog, vous savez que j'aime bien vous parler de technologie sur lesquels j'ai passé du temps, c'est le cas de Typesense, puisqu'il a été une grosse partie du projet sur lequel je travaille en ce moment.
Vous êtes prêt ? Alors c'est parti !
Typesense est un moteur de base de données indexée (et donc un moteur de recherche), Open Source, écrit en C++.
Sur son Github, il se définit comme étant une alternative Open Source à Algolia (Un "SaaS" propriétaire, offrant une API de recherche).
Pour interagir avec typesense, celui-ci expose une API REST, assez bien documentée. l'API permet de tout faire, par exemple créer des clefs d'accès avec des droits spécifiques, créer des collections, indexer des données ... etc.
Contrairement à un moteur de base de données relationnel, il n'y a pas de relation dans un moteur de base de données indexée, les données sont enregistrées "en brut", si par exemple vous avez une collection "Circuit" et que dedans vous avez un champ "type vélo" alors il y aura écrit autant de fois que nécessaire "Route" ou encore "VTT".
Voyez un peu ça comme un très grand tableau Excel.
Chaque ligne du tableau Excel est appelée un "document", et chaque colonne est appelée un "champs".
C'est vraiment basé sur le texte, il n'y a pas de logique autre derrière, c'est pour cela que c'est rapide.
Bien qu'elle ne soit pas spécifique à Typesense, voici quelques fonctionnalités que vous retrouverez dans la plupart des moteurs de recherche :
Les facettes
Vous connaissez forcément cela, vous l'avez déjà vu sur des sites e-commerces, c'est la possibilité de filtrer les résultats en fonction de critères, par exemple sur un site de vente de vélo, vous pouvez filtrer par "type de vélo" ou encore "taille de roue". Vous pouvez regarder sur la droite de cette page (en dessous sur mobile) pour voir de quoi l'on parle.
Résultat de recherche en fonction du "poids"
C'est très simple, cela veut dire que : certains champs sont plus importants que d'autres, par exemple si vous cherchez un nom de Ville comme Paris et que dans votre collection il y a un document avec comme champs « titre » : « Une balade en Île-de-France » et dans le champ « ville » : « Paris », alors si votre champ "titre" a un plus gros poids que le champ "ville", le moteur de recherche regardera en premier dans « titre » puis dans « ville », et donc triera les résultats de recherche en fonction de ça. Dans ce cas-là les documents qui ont « Paris » dans le champ « titre » sortiront avant ceux qui ont « Paris » dans le champ « ville ».
Déjà, ils ont des choses en commun, par exemple ils peuvent tous les deux fonctionner en cluster (sur plusieurs serveurs, cela permet d'avoir une haute disponibilité et de meilleures performances quand il y a du trafic).
Pour le reste :
À l'heure de l'écriture de ces lignes, la version "stable" est la version 0.24.1.
Cela peut se ressentir lorsque vous travaillez avec...
Voilà donc un « comportement » bizarre qui m'est tombé dessus lorsque je travaillais avec Typesense, il m'arrivait de faire beaucoup de modification de donnée de l'index et de laisser tourner Typesense sur ma machine de dev, à partir d’un certain temps, l'API était beaucoup plus lente, et parfois même, des données disparaissait carrément, par exemple quand je souhaitais faire un « update » sur un document, l'API me renvoyait que ce document n'existait pas... 😮
Le problème vient simplement du fait que lorsqu'on met à jour souvent les documents, Typesense a tendance à « bugger ».
J'imagine, et ce n'est que mon interprétation, que l'équipe travail plus sur la pertinence des reulstats de recherche ainsi que sur la rapidité que sur cette partie-là pour le moment.
Tout comme pour ElasticSearch avec ce bundle, un bundle est en cours de développement pour Typesense.
Tout comme Typesense lui-même, le Bundle est assez jeune, lors de mon travail je suis tombé sur un OS, dans mon cas à moi j'avais énormément d’entrées à indexer, et, à cette époque, le bundle envoyait tout d'un coup à Typesense sans pagination, plutôt que de l'envoyer en plusieurs requêtes...
Du coup j'étais prêt à coder l'import avec une pagination et faire une « pull request » sur le projet, mais on m'a devancé .
Si vous avez déjà utilisé celui pour ElasticSearch, vous ne serez pas dépaysé...
Pour fonctionner, le bundle écoute les événements "doctrine", pour détecter quand votre base de données est à mise à jour, et donc, mettre à jour la base de données indexée.
Comme je vous l'ai dit plus haut, il faut faire attention avec ce comportement, car Typesense n'aime pas trop quand il y a beaucoup de modifications sur les documents d'une collection.
Il peut être intéressant de noter également, que par défaut, tout comme le bundle pour ElasticSearch, quand on fait une requête, le bundle "Hydrate" les résultats avec les objets « Doctrin », et pour cela, il fait beaucoup de requête à votre base de données (MYSQL, Postgres ... etc), pensez à regarder si dans votre cas d'usage vous avez vraiment besoin des objets complets.
Tout comme Algolia, Typesense permet au front-end (le JavaScript) de s'y connecter directement, cela évite de passer par le back-end de votre application à chaque fois, c'est plus léger et plus réactif.
En plus de fournir le moteur de recherche, l'équipe de Typesense fournit également un client JavaScript, qui permet de faire des requêtes facilement vers les serveurs Typesense (car oui, le client prend en charge le fait qu'il y ai plusieurs « nodes ».
C'est très simple à utiliser, pour instancier votre client, regardez ce fichier de test qui montre comment faire.
Une fois que vous avez votre "client".
Une fois que vous avez instancié votre client, vous pouvez simplement faire une recherche de la manière suivante :
Le résultat sera sous forme de JSON, et si vous utilisez Symfony, pensez bien que là vous vous connectez directement à Typesense, donc il n'y a aucune hydratation.
InstantSearch est une librairie JavaScript proposée par Algolia pour créer des interfaces de recherche avancée, elle est intéressante, car de base elle est pas mal conçue et surtout, elle est extensible pour la faire se comporter comme vous vous le voulez.
Plus haut, je vous ai dit que Typesense se place comme alternative à Algolia, du coup il existe un adaptateur pour InstantSearch.
Son utilisation est très simple également, il suffit de l'instancier un peu à la manière de typesense-js et le passer à InstantSearch. Jetez un œil à la page Github du projet pour voir comment faire.
Une fois que vous avez instancié votre adaptateur, consultez la documentation d’InstantSearch
Une image vaut mieux que 1000 mots, donc je vous propose de tester directement :
Là, juste un « input », qui fait des requêtes simples
Les serveurs qui traitent vos requêtes se trouvent en France, à Paris, cela vous donne un bon exemple de ce qu'il est possible de faire avec Typesense.
Bien que ce soit un projet jeune, Typesense a, je pense, de l'avenir sur le marché des moteurs de recherche.
J'ai beaucoup aimé travailler avec et le réutiliserais quand j'en aurais l'occasion. Il me permet de créer l'expérience utilisateur que je veux créer.
À la prochaine 😁.