Volltextsuche in persistierten Objekten mit Hibernate Search

Das Hibernate Projekt bietet mit Hibernate Search die Möglichkeit, die in einer Datenbank persistierten Objekte bequem zu durchsuchen. Als Suchmaschine für die Volltextsuche kommt dabei Apache Lucene zum Einsatz. Die Einrichtung ist in nur wenigen Schritten erledigt:

  1. Zusätzlich zur vorhandenen Hibernate Installation müssen die Jar-Dateien aus dem Hibernate Search Release in das eigene Projekt eingebunden werden.
  2. Die Hibernate Konfiguration muss um 2 Properties ergänzt werden:
    <session-factory>
    ...
    <property name="hibernate.search.default.directory_provider">
    org.hibernate.search.store.FSDirectoryProvider
    </property>
    <property name="hibernate.search.default.indexBase">
    luceneIndexPfad
    </property>
    ...
    <session-factory>

    Die erste Property legt dabei den Directory-Provider fest. In diesem Fall wird der FSDirectoryProvider gewählt, der den Index für die Volltextsuche im Filesystem ablegt. Die zweite Property gibt das Basisverzeichnis für diesen Index an. Einige in Lucene bereits enthaltene Alternativen zu dem hier verwendeten Directory-Provider sind unter [1] beschrieben.

  3. Als nächstes müssen die Hibernate-Mappings der zu durchsuchenden Entitäten um einige Annotations ergänzt werden:
    1. Die Entity-Klasse muss zunächst um die Annotation
      @Indexed

      ergänzt werden. Optional kann hier noch mit

      @Analyzer(impl = MyAnalyzer.class)

      eine eigene Analyzer-Klasse angegeben werden, da der voreingestellte StandardAnalyzer nur für die Suche in englischen Texten optimiert ist und sich mit einem an die jeweilige Sprache angepaßten Analyzer bessere Ergebnisse erzielen lassen. Weitere Analyzer (u.A. für deutschsprachige Texte) findet man unter [2].

    2. Die zu durchsuchenden Felder werden mit
      @Field(index=Index.TOKENIZED)

      annotiert, wobei Index.TOKENIZED bedeutet, dass der Inhalt des Feldes beim Anlegen des Index in Tokens zerlegt wird. Dies ist nötig, damit später innerhalb des Feldes nach einzelnen Worten gesucht werden kann.

    3. Für jede Entität muss genau ein Feld mit der Annotation
      @DocumentId

      als Id für Lucene markiert werden. Dieses Feld muss ein Objekt innerhalb des gesamten Index eindeutig identifizieren (auch gegenüber Objekten andere Entity-Klassen).

Als nächstes muß der aktuelle Bestand erstmalig indexiert werden. Für eine vorhandene Hibernate Session mySession und eine Liste myArticles von Artikel-Objekten könnte das wie folgt geschehen:

FullTextSession fullTextSession = Search.createFullTextSession(mySession);
Transaction tx = fullTextSession.beginTransaction();
for (Article article : myArticles) {
   fullTextSession.index(article);
}
tx.commit();

Nachdem dies abgeschlossen ist, können Volltextsuchen durchgeführt werden. Neue Objekte werden zukünftig beim Persistieren automatisch in den Index aufgenommen.

Eine Suchanfrage mit vorhandener Hibernate Session mySession in einem Bestand von Artikeln, die ein mit @Field annotiertes Feld textContent haben, könnte dann wie folgt aussehen:

String searchTerm = "Hibernate";
FullTextSession fullTextSession = Search.createFullTextSession( mySession );
Transaction tx = fullTextSession.beginTransaction();
QueryParser parser = new QueryParser("textContent", new StandardAnalyzer());
org.apache.lucene.search.Query query = parser.parse( searchTerm );
org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery( query, Article.class );
List result = hibQuery.list();
tx.commit();
session.close();

Im Anschluß befinden sich in result alle Artikel, deren textContent das Wort Hibernate enthält. Neben der exakten Suche gibt es noch viele weitere Suchmöglichkeiten (z.B. mit Wildcards und unscharfe Suchen). Mehr zu diesem Thema findet man unter [3].


Malte Wulf

Tags: , ,

  • Share/Bookmark

Kommentare sind geschlossen.