Volltextsuche à la Lucene
Artikel erschienen in Swiss IT Magazine 2006/18
Lucene ist ein Apache-Projekt, das sicher nicht so im Rampenlicht steht wie beispielsweise myFaces, Struts oder der Apache Webserver, aber dennoch als Perle im Apache-Softwarepool angesehen werden kann. Bei Lucene handelt es sich um ein Framework zur (Volltext-) Indizierung von Datenbeständen sowie zur effizienten und flexiblen Suche in den Indizes. Es richtet sich somit ausschliesslich an Entwickler, die Such-Funktionalität in ihren Systemen implementieren möchten, und hat sich wegen seiner einfachen Anwendbarkeit, Flexibilität und Leistungsfähigkeit zum De-facto Standard entwickelt. So setzen auch verschiedene andere Open-Source-Projekte wie das Cocoon Framework Lucene ein, in dessen Rahmen es als Suchmaschine verwendet werden kann.
Möchte man Anwendungen entwickeln, die grössere Datenbestände effizient durchsuchen, so besteht dieses Vorhaben typischerweise aus drei Schritten:
- Zunächst sollte eine gewisse Struktur in die Daten gebracht werden. Für hochstrukturierte Datenbestände besteht das in der Regel darin, dass ein relationales Datenbankmodell erstellt wird und die Daten in einer entsprechenden Datenbank verwaltet werden. Ist der Datenbestand aber weniger gut strukturiert beziehungsweise heterogen und steht die Suche im Vordergrund, was die Domäne von Werkzeugen wie Lucene ist, definiert man in der Regel neben den Nutzdaten Metadaten, die auch die heterogenen Daten einigermassen gut beschreiben können. Ausserdem muss definiert werden, welche Daten überhaupt indiziert und welche Daten im Index mit abgelegt werden. Dies ist wichtig, da der Datenumfang einen erheblichen Einfluss auf den Umfang des Indexes sowie die Dauer des Indizierungsvorganges hat.
Im Gegensatz zu Datenbanken arbeitet Lucene immer mit «Dokumenten», wobei der Dokumentbegriff nicht zu wörtlich zu nehmen ist. Im Prinzip ist ein Dokument ein Container, der Metadaten enthält, und besteht technisch gesehen aus Feldern. Jedes Feld hat einen Namen und einen textuellen Inhalt. Wenn man nun alle Fotos auf einer Festplatte indizieren möchte, so könnte man ein Programm schreiben, das zunächst alle JPEG-Dateien sucht und dann mit einer geeigneten Bibliothek die EXIF-Header (Kameradaten) und IPTC-Metadaten (Stichworte, Ort, Name des Fotografen usw.), die in der Bilddatei gespeichert werden können, aus jedem Bild extrahiert.
Im Verständnis von Lucene könnte man also zum Beispiel die Felder Titel, Ort, Fotograf, Stichworte, Kurzbeschreibung, Aufnahmedatum, Dateiname und Ort der JPEG-Datei definieren. Diese werden pro Foto in einem Dokument zusammengefasst und dieses Dokument der Lucene-Indexing-Komponente übergeben. Diese ergänzt dann den jeweiligen Index um dieses «Dokument». Dabei kann man sich unter anderem noch entscheiden, ob ein Feld wie Stichworte oder Kurzbeschreibung in Tokens (einzelne Worte) zerlegt oder ob es ohne weitere Veränderung indiziert werden soll, wie man das bei Einzel-Informationsfeldern wie Datum oder Ort machen würde.
Der Dokument-Begriff muss sich aber nicht unbedingt auf ein tatsächliches Dokument oder eine real existierende Datei beziehen, wie das bei typischen Indizierungen von Office-Dokumenten oder PDFs der Fall ist. Man kann beispielsweise Ergebnisse einer SQL-Abfrage aus einer Datenbank in Lucene-«Dokumente» abfüllen und indizieren lassen oder die Webseiten, die ein Content-Management-System dynamisch erstellt und die somit gar nicht als reale Dokumente vorliegen. Ebenso in Frage kommen Daten aus XML Streams oder E-Mails eines Mailservers. Wichtig ist nur, dass es irgendeine eindeutige Möglichkeit gibt, auf die entsprechende Ressource zu verweisen. Andernfalls wäre es nicht möglich, von der Suche in den Metadaten auf die eigentlichen Nutzdaten zuzugreifen.
Im Beispiel der Fotoindizierung könnte der eindeutige Identifikator das Verzeichnis und der Dateiname sein, im Falle des CMS die URL und im Falle von Datenbankabfragen der Wert des Primärschlüssels.
keit, neue Dokumente in den Index aufzunehmen, alte zu löschen oder Dokumente zu ändern. Die Kernklassen sind hier IndexWriter, Document, Field sowie Analyzer für die verschiedenen Sprachen. Interessant ist hierbei, dass ein Index nicht unbedingt in einem Verzeichnis auf der Festplatte liegen muss. Die Index-Speicherung ist so abstrahiert, dass neben der Festplatte verschiedene Speicherorte wie RAM oder eine relationale Datenbank als Index-Speicher verwendet werden können.
Ein zweiter wichtiger Teil der Lucene-API kümmert sich um die eigentliche Suche und bietet verschiedenste Möglichkeiten, Suchen zu formulieren. Die wesentlichen Klassen sind:
- IndexSearcher
Neben der konkreten programmatischen Formulierung solcher Queries über die entsprechenden Klassen bietet Lucene eine QueryParser-Klasse an, die eine Lucene-spezifische Abfragesprache implementiert. Damit können von Menschen geschriebene Anfragen in das interne Lucene-Format übersetzt werden. So ist es möglich, schnell ein sehr mächtiges Such-Interface in eigenen Anwendungen anzubieten.
Aus der genannten Funktionalität lassen sich somit durchaus Parallelen zu Datenbanksystemen ziehen. So entspricht ein Dokument mit Feldern im Prinzip einer Tabelle einer relationalen Datenbank, wenngleich einige Einschränkungen existieren. Tatsächlich gibt es mittlerweile einige Anwender, die in bestimmten Anwendungsgebieten ihre Objekte gar nicht mehr in eine relationale Datenbank speichern, sondern beispielsweise als XML-Dokument auf der Festplatte ablegen und den Index mit Lucene erstellen lassen. Dies ist vor allem dann eine sehr einfache und schnelle Methode, um Daten verfügbar zu machen, wenn man einen vergleichsweise statischen Datenbestand mit wenig Änderungen und keine Transaktionen hat und der Schwerpunkt auf schneller Suche und effizientem Zugriff liegt.
Im Umfeld des Lucene-Frameworks sind viele weitere Projekte zu nennen, die Lucene verwenden oder den Einsatz von Lucene einfacher machen. Besonders erwähnenswert ist das Tool Luke (www.getopt.org/luke). Luke ist eine Java-Anwendung, die es erlaubt, beliebige Lucene-Indizes zu öffnen und zu analysieren. Man kann sich die Dokument- und Feldstruktur ansehen, die häufigsten Suchbegriffe anzeigen lassen oder Suchen absetzen.
Dieses Werkzeug ist ganz besonders für Entwickler von Lucene-Anwendungen empfehlenswert. Denn Lucene speichert Indizes aus Effizienzgründen in einem Binärformat ab, das mit normalen Editoren nicht vernünftig analysiert werden kann.
Mit Luke hat man aber die Möglichkeit, zu überprüfen, ob der Index tatsächlich so aussieht, wie man ihn geplant hat. Damit wird die Fehlersuche im Falle von Problemen vereinfacht.
Daneben existieren verschiedenste Open-Source-Anwendungen wie Eclipse oder die Groupware-Plattform Zimbra, die Lucene zur Suche verwenden.
Das Lucene-Projekt wurde im Jahr 2000 als Sourceforge-Projekt gestartet und ist 2002 zur Apache Software Foundation übergesiedelt. Im Augenblick liegt Lucene in der Version 2.0 vor. Es ist ein sehr stabiles Projekt und kann unbedingt für die genannten Anwendungsfälle empfohlen werden.
Die Dokumentation von Lucene besteht aus der Webseite, dem Wiki und der Javadoc-Dokumentation. Leider entspricht die Dokumentation nicht der Qualität des Projekts und dem Standard vieler anderer Apache-Projekte. Dies gilt besonders im Hinblick auf Einsteiger. Die Javadoc-Dokumentation ist zwar ausreichend, aber für den Start gibt es nur ein einfaches, aber schlecht beschriebenes Beispiel.
Überblick-Dokumentation, Beschreibung der Abfragesprache, Erklärung der Konzepte, Feature-Listen und einige andere Dinge sucht man in der offiziellen Distribution leider vergeblich. Allerdings existieren mittlerweile einige gute Artikel und Tutorials, die im Lucene-Wiki verlinkt sind, sowie zwei Bücher. Besonders «Lucene in Action» (ISBN 1-932394-28-1) ist empfehlenswert, wenn man Lucene ernsthaft einsetzen möchte.
Weiter ist erwähnenswert, dass der grosse Erfolg von Lucene in der Java-Welt dazu geführt hat, dass mittlerweile eine Unzahl an Portierungen auf andere Plattformen existiert, darunter Perl, Python, C++, .Net und Ruby. Dies alleine zeigt die Beliebtheit des Projektes. Allerdings muss man einschränkend anmerken, dass noch nicht alle Portierungen dieselbe Qualität aufweisen wie die ursprüngliche Java-Variante.
Anwendungszenario von Lucene
Alexander Schatten ( alexander@schatten.info ) ist Assistent am Institut für Softwaretechnik und interaktive Systeme der Technischen Universität Wien.