SeSQL : un moteur de recherche en Python etPostgreSQL
Yohann GABORY — Gaël LE MIGNOT
Pilot Systems
11 juillet 2011
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Plan1 Introduction
Le besoin initialL’historique du projet
2 Fonctionnalités de SeSQLIndexationRechercheFonctionnalités additionnelles
3 Fonctionnement interneGestion des dépendancesLes short queriesQuelques optimisationsBenchmarks
4 Perspectives pour l’avenirNouvelles fonctionnalitésIntégration à d’autres projets
5 ConclusionYohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Introduction
Introduction
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Contexte
Contexte général
Quotidien LibérationUtilisation en back-office dans un premier tempsUtilisation en frontal dans un second temps
Utilisation de la rechercheNavigationRecherches simplesRecherches documentaires
Solution précédentePropriétaire, sous Windows (TextML)Problèmes de performances et de stabilité
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Solution précédante
Schéma d’architecture
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Base d’indexation
Volumétrie703 701 articles169 017 pages4 064 478 commentaires (non indexées dans TextML)100k contenus divers
Types d’indexRecherche en texte pleinRecherche sur texte exactFiltres sur des méta-données : auteurs, catégories, . . .Tri par date
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Interface de recherche
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Version initiale
ContraintesDevait rester proche de l’architecture existanteDevait s’interfacer avec du code PHP/MySQL
SolutionUn webservice en PythonUne base PostgreSQL séparéeUne API globalement compatible avec celle de TextML
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Première version de SeSQL
Schéma d’architecture
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Deuxième version
ContexteL’ensemble du site est en cours de migration en DjangoOn souhaite s’épargner la lourdeur de l’API XMLOn souhaite rester aussi près que possible de Django
SolutionUne application DjangoLes recherches s’expriment avec l’objet Q de DjangoSeSQL renvoie des objets Django
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Deuxième version de SeSQL
Schéma d’architecture
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Fonctionnalités de SeSQL
Fonctionnalités de SeSQL
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Définition de l’indexation
Types d’indexTypes simples : entiers, dates, ...Champs full textChamp multi-valués (pour des relations par exemple)
Sources des indexChamps du modèleAppel à des méthodes du modèleSuivi des relationsIndex composite : concaténation, premier non vide, ...
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Intégration avec Django
Configuration de SeSQL
Une application comme une autre, qui doit être ajoutéedans le settings.py
Nécessite un back-end PostgreSQLA son propre fichier de configuration, sesql_config.py
Définition des modèles à indexerS’effectue via la TYPE_MAP dans la configurationPar défaut suit les héritagesPermet de regrouper les contenus cherchés souventensemblesSeSQL utilise un simple signal post_save
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Un sesql_config minimalisteFIELDS = (ClassField("classname"),
LongIntField("id"),DateTimeField("created_at"),FullTextField("user","user.screen_name"),LongIntField("user_id", "user.id"),FullTextField("text",
["text"],primary=True,dictionnary = ’public.lem_french’,
),)
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
un exemple d’intégration Rook : Recherche
1 500 000 Tweets en full textDes requètes complexes :tweets = Tweet.objects.filter(
user__relation__in = user.relation_set.filter(user_type = "followers")).filter(text__icontains = mot).order_by(’-created_at’)
Simplissime avec SeSQL :ids = request.user.relation_set.filter(user_type="friends").only(’id’)results = longquery(Q(user_id__in = ids)&
Q(text__containswords = request.GET[’search’] ))
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Gestion de la lexemisation
PrincipePrendre le radical des motsPeut être très compliqué : cheval, chevaux, chevaletDépend de la languePeut provoquer des effets de bord
Dans SeSQLUtilise les text search configuration de PostgreSQLSeSQL effectue un nettoyage supplémentaire (accents,majuscules, entités HTML, ...)Peut être défini de manière différente par index
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Description d’une recherche
Utilisation de l’objet QSeSQL utilise l’objet Q de DjangoIl permet de définir des recherches complexes, avec desET, OU, négations, ...Chaque élément est composé de : un index, un opérateuret une valeur
Les opérateursSur du texte : containswords, containsexact, ...Sur des tableaux : containsall, containsany, ...Opérateurs génériques : plus petit, plus grand, ...
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Long query et short query
Short queryRequêtes pour de la navigation, un portlet, un aperçu, ...Limité à un petit nombre (par exemple 50) de résultatsNe supporte pas le tri par pertinenceExtrêmement rapides
Long query
Supporte la pagination de manière stableEnvoi le nombre exact de résultatsPeut être plus lente dans certains cas
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Quelques bonus
Le triSur un index numérique ou de dateOu alors par pertinence, avec gestion :
de la pondération (le titre compte plus que le corps dutexte)de la proximité des mots cherchésde la fréquence des mots cherchés
Les résultatsSeSQLResultSet est un générateur Python, donc lazyRenvoi directement les objets Django à l’itérationLes objets peuvent être de plusieurs types
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Et en prime...
Aide au highlight
Un module spécial est fourniIl renvoi la liste des positions, en caractères, des motsayant été trouvés
SeSQL adminPermet d’utiliser SeSQL depuis l’admin DjangoAssez intrusif pour l’instant, donc désactivé par défaut
HistoriqueCollecte les historiques de recherche, en optionCompte le nombre de résultats et la fréquence desrecherches
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Fonctionnement interne
Fonctionnement interne
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Gestion des dépendances : le problème
Un exempleDans un module de Quizz, on veut indexer les réponsespossibles dans l’objet QuizzFacile à faire avec SeSQL et les index compositesMais si on modifie une réponse, on ne modifie pas l’objetQuizz
Les conséquencesOn veut pouvoir réindexer les objets liés quand onréindexe un objetMais il peut y en avoir énormément : imaginons qu’onchange le nom d’un auteur de 147 789 articles du journal !
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Gestion des dépendances : la solution
Le principeSeSQL stocke la liste des objets à ré-indexerUn daemon autonome s’occupe de les ré-indexer, petit àpetit
En pratiqueSeSQL ne détecte pas tout seul les objets liésLes modèles peuvent implémenter une méthodespécifique, qui indique à SeSQL ce qui doit être réindexéCette méthode peut renvoyer des objets ou des couples(class, id).
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Les short queries : le problème
Rappel du contexteTrouver les 50 articles les plus récentes sur un sujetDoit être le plus rapide possible
Les deux query plans1 Parcourir l’index sur les dates, et filtrer les articles2 Utiliser l’index sur les articles, puis trier sur les dates
La limite de PostgreSQL
PostgreSQL a des statistiques sur les motsMais un mot peut être avoir été fréquent mais ne plus l’être
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Exemple de plan 1
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Exemple de plan 2
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
L’heuristique
L’algorithme
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Recherche par texte exact
ProblèmePostgreSQL n’a pas d’index supportant çaFaire un LIKE sur toute la base est bien trop lent
La solutionOn commence pas filtrer, via l’index, en texte approchéPuis on refiltre avec un LIKE sur ce qui matché
La cas France 2Beaucoup d’article contiennent les deux motsMais peu le texte exact
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Les partitions
ProblèmeOn veut indexer du contenu très massif (les commentaires)On ne veut pas impacter les performances du reste
La solutionPostgreSQL supporte l’héritage de tablesOn indexe les commentaires dans une table à partOn ne cherche que dans une sous-table, si possibleSi non, on cherche dans la table maîtresse
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
There are three kinds of lies ...
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
... lies, damn lies and benchmarks
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Perspectives pour l’avenir
Perspectives pour l’avenir
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Quelques idées de nouvelles fonctionnalités
Suggestions de recherche
À partir de l’historiquePropose des recherches proches, fréquentes et ayantdonné de nombreux résultats
Gestion améliorée du multilingue
Ajout d’une détection automatique de la langueChoix de la bonne lexemisation en fonction de la languePouvoir restreindre la recherche par langue
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Possibilité d’intégration à d’autres projets
Hors Django
Implémenter une API pour avoir un mode webserviceImplémenter une API compatible avec le ZCatalog pourZope
Avec d’autres projetsIntégration possible avec haystack ?Avec des moteurs de classification ?
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Conclusion
Conclusion
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
Conclusion
Situation actuelleSeSQL disponible en GPL sur bitbucketUtilisé en production sur Libération (front et back)Utilisé sur d’autres projets comme Rook
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL
En attendant
Remerciementsaux communautés PostgreSQL, Python et Djangoà Libération de nous avoir fait confianceà Jérôme Petazzoni qui a contribué à la conception
La page de pub
Pilot Systems, société de services en logiciels libres :http://www.pilotsystems.net
Slides en licence CC-By-Sahttp://contributions.pilotsystems.net/
Des questions ?
Yohann GABORY — Gaël LE MIGNOT Pilot Systems SeSQL : un moteur de recherche en Python et PostgreSQL