Lucene und Hibernate Search

Searching oder Retrieving Information ist nach wie vor eine der wichtigsten Anforderungen in der aktuellen Entwicklung von JEE-Anwendungen. Der Content eines JEE-Projekts, bzw. einer Webanwendung wird meistens in relationalen Datenbanken gespeichert. Wie kann der Content suchfähig gemacht werden? Wie kann beim Suchen über große Datenmengen eine effiziente Performanz erreicht werden, wenn es sich hier um komplexe Texte handelt? Verwendet man den traditionellen LIKE oder JOIN Operator im SQL, konzentriert man sich auf SQL Statements und es führt dazu, dass die Persistenzschicht schnell komplex, umständlich in der Entwicklung und schwierig zu warten ist. Auf der anderen Seite ist die Transparenz des Zugriffs der Anwendung auf in der relationale Datenbank gespeicherten Content nicht möglich und es ergibt sich ein Performanceverlust bei großen Datenmengen.

Um diese oben genannten Probleme zu lösen gibt es verschiedene Möglichkeiten. Die meistverwendetste Lösung ist die Kombination von Hibernate, Lucene und Hibernate Search. Um die Transparenz zu ermöglichen wirdHibernate zur Realisierung der Persistenzschicht eingesetzt. Um die Anwendung suchfähig zu machen, werden Lucene zusammen mit Hibernate Search verwendet.

Lucene ist eine von Apache Jakarta Gruppe entwickelte Open Source Bibliothek für Volltextsuche. Lucene wird in Java implementiert und bietet zahlreiche Funktionen für die Abfrage von Informationen aus Textdokumenten an.

Hibernate Search ist ein Open Source Projekt, der Hibernate und Lucene verwendet, um die Volltextsuche über persistente Domänenmodelle anzubieten. Mit Hilfe von Hibernate Search kann Lucene leicht in die Hibernate Schicht integriert werden. Hibernate Search läuft über Lucene und ermöglicht die Indexierung durch Annotation über die Domänenklassen. Ohne den Einsatz von Hibernate Search müssen wir die Synchronisierung von Datenbank und Index übernehmen. Hibernate Search bietet eine explizite API an, um manuelle Indexierung oder Entfernung einer Entität von dem Index aufzurufen. Dies ist sehr hilfreich, wenn Content schon vorhanden aber noch nicht indiziert ist, welcher auf die Volltextsuche-Funktionen aber aufgefordert werden soll.

Um die Integration der Volltextsuche zu realisieren müssen folgende Schritte durchgeführt werden:

  • Die Domänenmodell-Objekte annotieren
  • Directory Provider auswählen
  • Pfad zum Index angeben
  • Indexierung einschalten
  • Suchen

Domänenmodell-Objekte nach dem Hinzufügen der Annotation:

Die Domänenmodell-Objekte annotieren

Jedes zu indizierende Domänenobjekt muss mit der @Indexed – Annotation gekennzeichnet werden. Die Id des Objekts wird als IndexID mit @DocumentId annotiert. Diese IndexId muss innerhalb eines Index eindeutig sein. Die Felder Name, Vorname, Geburtsdatum, Strasse, Hausnummer und PLZ werden mit dem Parameterindex=Index.TOKENIZED annotiert, damit die Inhalte dieser Felder von dem Tokenizer analysiert werden. Alle Felder werden mit dem Parameter store.NO annotiert. Der Parameter store.NO gibt an, dass die indizierten Inhalte nicht im Index abgespeichert werden.

Hibernate Search bietet auch an, die Beziehung 1:1, 1:n und m:n nachzuvollziehen. In diesem Fall wird in der Adresse person mit der Annotation @IndexedEmbedded annotiert. Dies führt dazu, dass alle in der Person zur Indizierung annotierten Felder auch mit in dem Index Adresse aufgenommen.

Directory Provider und Pfad zum Index angeben

Nachdem alle Domänenmodell-Objekte mit Hibernate Search Annotation bereitgestellt werden, wird das Dateisystem als Directory Provider zur Speicherung von Index angegeben Und anschließend der Pfad zum Index. Das ist das Verzeichnis, in dem sich die Indexe aller Domänenobjekte der Anwendung befinden.

Indexierung einschalten

Es ist möglich, jedes Domänenobjekt oder eine Liste von Domänenobjekten zu indizieren.

Nach dem Indizieren haben wir im Ordner home/phungq/index zwei Verzeichnisse
    . luc.bsp.entity.Person
    . luc.bsp.entity.Adresse
wobei jedes die Index Dateien enthält

Suchen

Das Suchen fängt mit der Erzeugung der FullTextSession an. Danach wird der MultiFieldQueryParser mit zwei Parametern initialisiert, einem Array, bestehend aus den zu suchenden Feldern, und dem Analyzer. Mit dem MultiFieldQueryParser ist es möglich, mehrere Felder gleichzeitig in eine Suchanfrage zu kombinieren. Dieser Parser ruft die parse Methode mit dem übergegebenem Suchmuster auf. Für das Suchmuster stehen viele Möglichkeiten der Lucene Query Syntax zur Verfügung. Anschließend wird eine Volltextsuche-Anfrage mit Hilfe der createFullTextQuery-Methode erstellt und in Form einer Hibernate-Anfrage zurückgegeben.

Eine Suchmaschine ist eine unverzichtbare Anforderung in der modernen JEE-Anwendung. Sie kann mit Lucene und Hibernate Search leicht in der JEE-Anwendung integriert werden. Ich persönlich finde, dass die Kombination zwischen Lucene und Hibernate Search den Entwicklern eine flexible, leicht zu implementierende und mächtige Lösung für die Volltextsuche anbietet, wenn es sich bei dem Inhalt um umfangreiche Texte handelt.

Das Ziel, des in diesem Blog eingeführten Beispiels ist es zu zeigen, wie bereits in einem frühen Stadium der Implementierung eine einfache Integration der Volltextsuche mit Lucene und Hibernate Search möglich ist. Weitere Informationen sind auf folgenden Webseiten zu erhalten:

Apache Lucene: http://lucene.apache.org/
Hibernate Search: http://www.hibernate.org/subprojects/search.html