Premiers pas avec Lucene : Recherche dans l'index

Dans la continuité de l'entrée précédente, qui parlait de l'indexation de données avec Lucene, je vais aujourd'hui parler des Query, les objets permettant de faire des requêtes de recherche dans l'index.

Prenons un petit exemple ; dans l'index que nous avons créé hier, essayons de rechercher les documents dont le content contient le mot-clé "Java".

Les différentes étapes à suivre dont les suivantes :
  1. Créer un IndexReader, un objet capable de lire l'index.
  2. Créer un objet de type IndexSearcher, un objet capable de faire une recherche dans un index, à travers un IndexReader.
  3. Créer un objet de type QueryParser. Cet objet va parser la requête passée, et l'interpréter afin de fournir les résultats les plus pertinents.
  4. Parser la requête, nous obtiendrons un objet de type Query, contenant la requête à exécuter.
  5. Exécuter la requête, qui nous renvera une liste de résultats (sous la forme d'un objet de type Hits, contenant les résultats.
  6. Itérer sur cette liste, afin d'afficher les résultats de notre recherche.

Un petit exemple de code pour concrétiser tout ça :
IndexReader index = IndexReader.open(INDEX_ROOT);
Searcher searcher = new IndexSearcher(index);
QueryParser parser = new QueryParser("content", new StandardAnalyzer());
Query results = parser.parse("Java");
Hits hits = searcher.search(results);
Iterator<Hit> iterator = hits.iterator();
while (iterator.hasNext()) {
    Hit hit = iterator.next();
    System.out.println(hit.get("title") + ", by " + hit.get("author"));
}

Les résultats sont automatiquement triés par pertinence. Il est possible de récupérer un "score" représentatif de la pertinence d'un résultat grâce à la méthode Hit.getScore().


Voici donc un premier et rapide aperçu du mécanisme de requêtes dans des index Lucene. Le système de requête en entier est bien plus complexe, et permet des requêtes beaucoup plus poussées. Je continuerais donc cette série d'articles au fur et à mesure de mes découvertes. En attendant, la documentation officielle de Lucene est très complète.

Permalink  |  Commentaires (0)

Premiers pas avec Lucene : Création d'un index

Je viens de faire mes premiers pas avec Lucene (la version Java), une librarie permettant de faire de l'indexation.

Ma première impression par rapport à cette librarie est très simple : J'aime Lucene.

Le maniement est très simple, autant pour indexer des données que pour les récupérer. L'exécution est très rapide. Tout est bien dans le meilleur des mondes.

Ce billet est le premier d'une petite suite ayant pour thème l'utilisation de Lucene. D'autres suivront, pour parler notament de la récupération des données stockées dans l'index. Au sujet de ce premier billet donc : la création d'un index, avec insertion de données à l'interieur.

La création des données se base sur un principe assez simple : on indexe un Document, qui est un objet spécifique à Lucene. Ce ducument est un ensemble de champs, nommés Fields. Un champ correspond à un attribut du document à stocker : contenu, auteur, date de modification, etc... Un champ peut être stocké, non stocké, ou compressé. Un champ peut également être indexé, non-indexé, indexé en suivant un Analyzer (un objet qui modifie les données à indexer, comme par exemple supprimer "le", "la", "l'", ...).

Un petit exemple, pour stocker un document qui contient un auteur, un contenu et un titre :
IndexWriter index = new IndexWriter(new File("index_root"), new StandardAnalyzer(), true);
Document document = new Document();
document.add(new Field("author", "viv", Field.Store.YES, Field.Index.UN_TOKENIZED));
document.add(new Field("title", "Lucene is great", Field.Store.YES, Field.Index.UN_TOKENIZED));
document.add(new Field("content", myDocumentContent, Field.Store.NO, Field.Index.TOKENIZED));
index.addDocument(document);
index.optimize();
index.close();

Petite explication de ce morceau de code :
  • On commence par créer un IndexWriter. Cet objet sera capable d'écrire des données dans l'index. L'index sera stocké dans un répertoire nommé index_root. L'analyseur syntaxique qui se chargera de nettoyer le contenu à indexer sera un nouveau StandardAnalyzer. Et enfin, le true permet de dire à notre IndexWriter de créer un nouvel index (en supprimant un ancien éventuellement trouvé)
  • Ensuite on crée notre Document.
  • On lui ajoute un premier Field, qui aura pour nom author et pour contenu viv. Le contenu du champ sera stocké dans l'index (Field.Store.YES). Et enfin, le champ sera indexé tel quel (Field.Index.UN_TOKENIZED).
  • Il en sera de même pour title.
  • Enfin, on ajoute un contenu content à notre document. Ce champ ne sera pas stocké (Field.Store.NO), mais sera quand même indexé. Enfin, le contenu indexé sera le contenu renvoyé par notre StandardAnalyzer (Field.Index.TOKENIZED).
  • Enfin, on ajoute notre document dans notre index, puis on optimise notre index, avant de le fermer.

L'ajout de données dans l'index est donc très simple. Il suffit de savoir quoi indexer. Une petite astuce consiste à ne stocker que ce dont on a besoin. Dans notre exemple, le contenu n'est pas stocké, car il serait trop volumineux et une indexation suffit amplement. L'auteur et le titre sont conservés pour pouvoir retrouver l'article d'origine lors d'une recherche ultérieure.


Voilà en ce qui concerne l'ajout de données dans un index Lucene. Le prochain billet de cette série parlera sûrement des requêtes dans un index Lucene, pour rechercher des données qui ont été indexées.

Permalink  |  Commentaires (0)