Le moteur de recherche Lucene: puissant, flexible et gratuit

Ne vous laissez pas tromper par le faible numéro de version - 0.04 en août 2000. Le moteur de recherche Lucene est une boîte à outils de recherche robuste, puissante et flexible, prête à résoudre de nombreux problèmes de recherche courants. Et comme il est maintenant disponible sous la licence open source LGPL plus flexible, le prix (gratuit!) Est également correct.

Doug Cutting, un développeur expérimenté d'outils de recherche et d'extraction de texte, a créé Lucene. Cutting est le principal auteur du moteur de recherche V-Twin (qui fait partie de l'effort du système d'exploitation Copland d'Apple) et est actuellement architecte principal chez Excite. Il a conçu Lucene pour faciliter l'ajout de capacités d'indexation et de recherche à un large éventail d'applications, notamment:

  • E-mail de recherche: une application de messagerie peut permettre aux utilisateurs de rechercher des messages archivés et d'ajouter de nouveaux messages à l'index à mesure qu'ils arrivent.
  • Recherche de documentation en ligne: un lecteur de documentation - sur CD, sur le Web ou intégré à l'application - pourrait permettre aux utilisateurs de rechercher de la documentation en ligne ou des publications archivées.
  • Pages Web consultables: un navigateur Web ou un serveur proxy pourrait créer un moteur de recherche personnel pour indexer chaque page Web visitée par un utilisateur, permettant ainsi aux utilisateurs de revoir facilement les pages.
  • Recherche de site Web: un programme CGI peut permettre aux utilisateurs de rechercher votre site Web.
  • Recherche de contenu: une application peut permettre à l'utilisateur de rechercher des documents enregistrés pour un contenu spécifique; cela pourrait être intégré dans la boîte de dialogue Ouvrir un document.
  • Contrôle de version et gestion de contenu: un système de gestion de documents peut indexer des documents ou des versions de documents, afin qu'ils puissent être facilement récupérés.
  • Flux d'actualités et de services filaires: un serveur ou un relais d'actualités peut indexer les articles à mesure qu'ils arrivent.

Bien sûr, de nombreux moteurs de recherche pourraient exécuter la plupart de ces fonctions, mais peu d'outils de recherche open source offrent la facilité d'utilisation, la rapidité de mise en œuvre et la flexibilité de Lucene.

J'ai d'abord utilisé Lucene lors du développement d'Eyebrowse, un outil open source basé sur Java pour cataloguer et parcourir les listes de diffusion. (Voir Ressources pour un lien.) Une exigence de base pour Eyebrowse était la capacité flexible de recherche et de récupération des messages. Il exigeait un composant d'indexation et de recherche qui mettrait à jour efficacement la base d'index à mesure que de nouveaux messages arrivaient, permettrait à plusieurs utilisateurs de rechercher et de mettre à jour la base d'index simultanément et de passer à des archives contenant des millions de messages.

Tous les autres moteurs de recherche open source que j'ai évalués, y compris Swish-E, Glimpse, iSearch et libibex, étaient mal adaptés aux exigences d'Eyebrowse d'une certaine manière. Cela aurait rendu l'intégration problématique et / ou longue. Avec Lucene, j'ai ajouté l'indexation et la recherche à Eyebrowse en un peu plus d'une demi-journée, du téléchargement initial au code entièrement fonctionnel! Cela représentait moins d'un dixième du temps de développement que j'avais budgété, et a donné un résultat plus étroitement intégré et riche en fonctionnalités que tout autre outil de recherche que j'ai envisagé.

Comment fonctionnent les moteurs de recherche

La création et la maintenance d'un index inversé est le problème central lors de la création d'un moteur de recherche de mots clés efficace. Pour indexer un document, vous devez d'abord le numériser pour produire une liste de publications. Les publications décrivent les occurrences d'un mot dans un document; ils incluent généralement le mot, un identifiant de document et éventuellement le (s) emplacement (s) ou la fréquence du mot dans le document.

Si vous considérez les publications comme des tuples du formulaire , un ensemble de documents produira une liste de publications triées par ID de document. Mais afin de trouver efficacement des documents contenant des mots spécifiques, vous devez plutôt trier les publications par mot (ou par mot et par document, ce qui accélérera les recherches multi-mots). En ce sens, la création d'un index de recherche est essentiellement un problème de tri. L'index de recherche est une liste de publications triées par mot.

Une mise en œuvre innovante

La plupart des moteurs de recherche utilisent des arbres B pour maintenir l'index; ils sont relativement stables en ce qui concerne l'insertion et ont des caractéristiques d'E / S bien comportées (les recherches et les insertions sont des opérations O (log n)). Lucene adopte une approche légèrement différente: plutôt que de maintenir un seul index, il construit plusieurs segments d'index et les fusionne périodiquement. Pour chaque nouveau document indexé, Lucene crée un nouveau segment d'index, mais il fusionne rapidement les petits segments avec les plus grands - cela réduit le nombre total de segments afin que les recherches restent rapides. Pour optimiser l'index pour une recherche rapide, Lucene peut fusionner tous les segments en un seul, ce qui est utile pour les index rarement mis à jour. Pour éviter les conflits (ou la surcharge de verrouillage) entre les lecteurs d'index et les rédacteurs, Lucene ne modifie jamais les segments en place, il n'en crée que de nouveaux. Lors de la fusion de segments,Lucene écrit un nouveau segment et supprime les anciens - après que tous les lecteurs actifs l'aient fermé. Cette approche s'adapte bien, offre au développeur un degré élevé de flexibilité dans le compromis entre la vitesse d'indexation et la vitesse de recherche, et présente des caractéristiques d'E / S souhaitables pour la fusion et la recherche.

Un segment d'index Lucene se compose de plusieurs fichiers:

  • Un index de dictionnaire contenant une entrée pour chaque 100 entrées du dictionnaire
  • Un dictionnaire contenant une entrée pour chaque mot unique
  • Un fichier d'écritures contenant une entrée pour chaque affichage

Puisque Lucene ne met jamais à jour les segments sur place, ils peuvent être stockés dans des fichiers plats au lieu d'arbres B compliqués. Pour une récupération rapide, l'index du dictionnaire contient des décalages dans le fichier de dictionnaire et le dictionnaire contient des décalages dans le fichier des publications. Lucene met également en œuvre une variété d'astuces pour compresser le dictionnaire et publier des fichiers - réduisant ainsi les E / S disque - sans entraîner de surcharge CPU importante.

Évaluer les moteurs de recherche

Parmi les autres moteurs de recherche open source largement utilisés, citons Swish-E, Glimpse, libibex, freeWAIS et iSearch. Comme tout logiciel, chacun est optimisé pour une utilisation dans des situations particulières; il est souvent difficile de déployer ces outils en dehors de leurs domaines prévus. Tenez compte des fonctionnalités suivantes lors de l'évaluation d'un moteur de recherche:

  • Indexation incrémentielle ou par lots: certains moteurs de recherche ne prennent en charge que l'indexation par lots; une fois qu'ils ont créé un index pour un ensemble de documents, l'ajout de nouveaux documents devient difficile sans réindexer tous les documents. L'indexation incrémentielle permet d'ajouter facilement des documents à un index existant. Pour certaines applications, comme celles qui gèrent les flux de données en direct, l'indexation incrémentielle est essentielle. Lucene prend en charge les deux types d'indexation.
  • Sources de données: de nombreux moteurs de recherche ne peuvent indexer que des fichiers ou des pages Web. Cela handicape les applications où les données indexées proviennent d'une base de données ou lorsque plusieurs documents virtuels existent dans un seul fichier, comme une archive ZIP. Lucene permet aux développeurs de fournir le document à l'indexeur via un Stringou un InputStream, permettant à la source de données d'être extraite des données. Cependant, avec cette approche, le développeur doit fournir les lecteurs appropriés pour les données.
  • Contrôle d'indexation: certains moteurs de recherche peuvent explorer automatiquement une arborescence de répertoires ou un site Web pour trouver des documents à indexer. Bien que cela soit pratique si vos données sont déjà stockées de cette manière, les indexeurs basés sur les robots d'indexation offrent souvent une flexibilité limitée pour les applications qui nécessitent un contrôle fin sur les documents indexés. Puisque Lucene fonctionne principalement en mode incrémentiel, il permet à l'application de trouver et de récupérer des documents.
  • Formats de fichier: certains moteurs de recherche ne peuvent indexer que du texte ou des documents HTML; d'autres prennent en charge un mécanisme de filtrage, qui offre une alternative simple à l'indexation des documents de traitement de texte, des documents SGML et d'autres formats de fichiers. Lucene soutient un tel mécanisme.
  • Balisage de contenu: certains moteurs de recherche traitent un document comme un seul flux de jetons; d'autres permettent la spécification de plusieurs champs de données dans un document, tels que «sujet», «résumé», «auteur» et «corps». Cela permet des requêtes sémantiquement plus riches telles que «l'auteur contient Hamilton ET le corps contient la constitution». Lucene prend en charge le balisage de contenu en traitant les documents comme des collections de champs et prend en charge les requêtes qui spécifient le ou les champs à rechercher.
  • Traitement de mots vides : les mots courants, tels que "a", "et" et "le", ajoutent peu de valeur à un index de recherche. Mais comme ces mots sont si courants, leur catalogage contribuera considérablement au temps d'indexation et à la taille de l'index. La plupart des moteurs de recherche n'indexeront pas certains mots, appelés mots vides. Certains utilisent une liste de mots vides, tandis que d'autres sélectionnent statistiquement les mots vides. Lucene gère les mots vides avec le Analyzermécanisme plus général , qui sera décrit plus tard, et fournit la StopAnalyzerclasse, qui élimine les mots vides du flux d'entrée.
  • Racine: Souvent, un utilisateur souhaite qu'une requête pour un mot corresponde à d'autres mots similaires. Par exemple, une requête pour «sauter» devrait probablement également correspondre aux mots «sauté», «cavalier» ou «sauts». La réduction d' un mot à sa forme de racine est appelée issue . Lucene n'implémente pas encore le stemming, mais vous pouvez facilement ajouter un stemmer via une Analyzerclasse plus sophistiquée .
  • Fonctionnalités de requête: les moteurs de recherche prennent en charge diverses fonctionnalités de requête. Certains prennent en charge les requêtes booléennes complètes; d' autres prennent en charge uniquement et requêtes. Certains renvoient un score de «pertinence» à chaque appel. Certains peuvent gérer des requêtes de contiguïté ou de proximité - "recherche suivie par le moteur" ou "Knicks near Celtics" - d'autres ne peuvent rechercher que des mots clés uniques. Certains peuvent rechercher plusieurs index à la fois et fusionner les résultats pour donner un score de pertinence significatif. Lucene prend en charge un large éventail de fonctionnalités de requête, y compris toutes celles répertoriées ci-dessus. Cependant, Lucene ne prend pas en charge la précieuse requête Soundex, ou "sonne comme".
  • Concurrence: plusieurs utilisateurs peuvent-ils rechercher un index en même temps? Un utilisateur peut-il rechercher un index pendant qu'un autre le met à jour? Lucene permet aux utilisateurs de rechercher un index de manière transactionnelle, même si un autre utilisateur met simultanément à jour l'index.
  • Prise en charge non anglaise: de nombreux moteurs de recherche supposent implicitement que l'anglais est la langue cible; cela est évident dans des domaines tels que les listes de mots vides, les algorithmes de dérivation et l'utilisation de la proximité pour faire correspondre les requêtes d'expression. Lorsque Lucene prétraite le flux d'entrée via la Analyzerclasse fournie par le développeur, il est possible d'effectuer un filtrage spécifique au langage.

Bien que nullement exhaustive, la liste ci-dessus offre un point de départ pour évaluer un moteur de recherche pour un projet particulier. Certains outils de recherche sont mal adaptés à certaines tâches - la compréhension des exigences de votre application peut vous aider à choisir le bon outil pour le travail.

Utilisation de Lucene

Je vais illustrer comment utiliser Lucene pour créer, remplir et rechercher un index. Pour plus de clarté, les instructions d'importation et la gestion des exceptions ont été omises des exemples de programmes. Dans ces illustrations, j'ai stocké l'index de recherche dans le système de fichiers (vous pouvez stocker des index n'importe où, par exemple, en mémoire ou dans une base de données). Les fichiers indexés sont de simples fichiers texte. Avec Lucene, vous pouvez également facilement indexer d'autres formats de documents et des documents non stockés dans des fichiers.

Créer un index

The simple program CreateIndex.java creates an empty index by generating an IndexWriter object and instructing it to build an empty index. In this example, the name of the directory that will store the index is specified on the command line.

public class CreateIndex { // usage: CreateIndex index-directory public static void main(String[] args) throws Exception { String indexPath = args[0]; IndexWriter writer; // An index is created by opening an IndexWriter with the // create argument set to true. writer = new IndexWriter(indexPath, null, true); writer.close(); } } 

Index text documents

IndexFile.java shows how to add documents -- the files named on the command line -- to an index. For each file, IndexFiles creates a Document object, then calls IndexWriter.addDocument to add it to the index. From Lucene's point of view, a Document is a collection of fields that are name-value pairs. A Field can obtain its value from a String, for short fields, or an InputStream, for long fields. Using fields allows you to partition a document into separately searchable and indexable sections, and to associate metadata -- such as name, author, or modification date -- with a document. For example, when storing mail messages, you could put a message's subject, author, date, and body in separate fields, then build semantically richer queries like "subject contains Java AND author contains Gosling." In the code below, we store two fields in each Document: path, to identify the original file path so it can be retrieved later, and body, for the file's contents.

public class IndexFiles { // usage: IndexFiles index-path file . . . public static void main(String[] args) throws Exception { String indexPath = args[0]; IndexWriter writer; writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false); for (int i=1; i