Die Lucene-Suchmaschine: Leistungsstark, flexibel und kostenlos

Lassen Sie sich nicht von der niedrigen Versionsnummer - 0,04 ab August 2000 - täuschen. Die Lucene-Suchmaschine ist ein robustes, leistungsstarkes und flexibles Such-Toolkit, mit dem viele häufig auftretende Suchprobleme gelöst werden können. Und da es jetzt unter der flexibleren LGPL Open Source-Lizenz erhältlich ist, stimmt auch der Preis (kostenlos!).

Doug Cutting, ein erfahrener Entwickler von Tools zum Suchen und Abrufen von Texten, hat Lucene entwickelt. Cutting ist der Hauptautor der V-Twin-Suchmaschine (Teil des Copland-Betriebssystems von Apple) und derzeit leitender Architekt bei Excite. Er entwarf Lucene, um das Hinzufügen von Indizierungs- und Suchfunktionen zu einer breiten Palette von Anwendungen zu vereinfachen, darunter:

  • Durchsuchbare E-Mail: Mit einer E-Mail-Anwendung können Benutzer archivierte Nachrichten durchsuchen und dem Index neue Nachrichten hinzufügen, sobald sie eintreffen.
  • Online-Dokumentationssuche: Mit einem Dokumentationsleser - CD-basiert, webbasiert oder in die Anwendung eingebettet - können Benutzer Online-Dokumentationen oder archivierte Veröffentlichungen durchsuchen.
  • Durchsuchbare Webseiten: Ein Webbrowser oder Proxyserver kann eine persönliche Suchmaschine erstellen, um jede von einem Benutzer besuchte Webseite zu indizieren, sodass Benutzer Seiten problemlos erneut aufrufen können.
  • Website-Suche: Mit einem CGI-Programm können Benutzer Ihre Website durchsuchen.
  • Inhaltssuche: Mit einer Anwendung kann der Benutzer gespeicherte Dokumente nach bestimmten Inhalten durchsuchen. Dies könnte in den Dialog Dokument öffnen integriert werden.
  • Versionskontrolle und Inhaltsverwaltung: Ein Dokumentenverwaltungssystem kann Dokumente oder Dokumentversionen indizieren, damit sie leicht abgerufen werden können.
  • News- und Wire-Service-Feeds: Ein News-Server oder Relay kann Artikel indizieren, sobald sie eintreffen.

Natürlich könnten viele Suchmaschinen die meisten dieser Funktionen ausführen, aber nur wenige Open-Source-Suchwerkzeuge bieten Lucene Benutzerfreundlichkeit, schnelle Implementierung und Flexibilität.

Ich habe Lucene zum ersten Mal bei der Entwicklung von Eyebrowse verwendet, einem Open-Source-Java-basierten Tool zum Katalogisieren und Durchsuchen von Mailinglisten. (Einen Link finden Sie unter Ressourcen.) Eine Grundvoraussetzung für Eyebrowse war die flexible Funktion zum Suchen und Abrufen von Nachrichten. Es wurde eine Indizierungs- und Suchkomponente benötigt, die die Indexbasis bei Eintreffen neuer Nachrichten effizient aktualisiert, es mehreren Benutzern ermöglicht, die Indexbasis gleichzeitig zu suchen und zu aktualisieren und auf Archive mit Millionen von Nachrichten zu skalieren.

Jede andere von mir evaluierte Open-Source-Suchmaschine, einschließlich Swish-E, Glimpse, iSearch und libibex, war in irgendeiner Weise schlecht für die Anforderungen von Eyebrowse geeignet. Dies hätte die Integration problematisch und / oder zeitaufwändig gemacht. Mit Lucene habe ich Eyebrowse in etwas mehr als einem halben Tag indiziert und gesucht, vom ersten Download bis zum voll funktionsfähigen Code! Dies war weniger als ein Zehntel der von mir budgetierten Entwicklungszeit und lieferte ein enger integriertes und funktionsreiches Ergebnis als jedes andere Suchwerkzeug, das ich in Betracht zog.

Wie Suchmaschinen funktionieren

Das Erstellen und Verwalten eines invertierten Index ist das zentrale Problem beim Aufbau einer effizienten Schlüsselwortsuchmaschine. Um ein Dokument zu indizieren, müssen Sie es zuerst scannen, um eine Liste der Buchungen zu erstellen . Buchungen beschreiben das Auftreten eines Wortes in einem Dokument. Sie enthalten im Allgemeinen das Wort, eine Dokument-ID und möglicherweise die Position (en) oder Häufigkeit des Wortes innerhalb des Dokuments.

Wenn Sie sich die Buchungen als Tupel des Formulars vorstellen, ergibt eine Reihe von Dokumenten eine Liste der Buchungen, sortiert nach Dokument-ID. Um jedoch Dokumente, die bestimmte Wörter enthalten, effizient zu finden, sollten Sie die Buchungen stattdessen nach Wort sortieren (oder nach Wort und Dokument, wodurch die Suche nach mehreren Wörtern beschleunigt wird). In diesem Sinne ist das Erstellen eines Suchindex grundsätzlich ein Sortierproblem. Der Suchindex ist eine Liste von Postings, sortiert nach Wörtern.

Eine innovative Umsetzung

Die meisten Suchmaschinen verwenden B-Bäume, um den Index zu pflegen. Sie sind relativ stabil in Bezug auf das Einfügen und weisen gut verhaltene E / A-Eigenschaften auf (Nachschlagen und Einfügen sind O (log n) -Operationen). Lucene verfolgt einen etwas anderen Ansatz: Anstatt einen einzelnen Index beizubehalten, werden mehrere Indexsegmente erstellt und regelmäßig zusammengeführt. Für jedes neue indizierte Dokument erstellt Lucene ein neues Indexsegment, führt jedoch schnell kleine Segmente mit größeren zusammen. Dadurch bleibt die Gesamtzahl der Segmente klein, sodass die Suche schnell bleibt. Um den Index für eine schnelle Suche zu optimieren, kann Lucene alle Segmente zu einem zusammenführen. Dies ist nützlich für selten aktualisierte Indizes. Um Konflikte (oder das Sperren des Overheads) zwischen Indexlesern und -schreibern zu vermeiden, ändert Lucene niemals vorhandene Segmente, sondern erstellt nur neue. Beim Zusammenführen von SegmentenLucene schreibt ein neues Segment und löscht die alten - nachdem aktive Leser es geschlossen haben. Dieser Ansatz lässt sich gut skalieren, bietet dem Entwickler ein hohes Maß an Flexibilität beim Abwägen der Indexierungsgeschwindigkeit gegen die Suchgeschwindigkeit und weist wünschenswerte E / A-Eigenschaften sowohl für das Zusammenführen als auch für das Suchen auf.

Ein Lucene-Indexsegment besteht aus mehreren Dateien:

  • Ein Wörterbuchindex mit einem Eintrag für jeweils 100 Einträge im Wörterbuch
  • Ein Wörterbuch mit einem Eintrag für jedes einzelne Wort
  • Eine Buchungsdatei mit einem Eintrag für jede Buchung

Da Lucene niemals Segmente an Ort und Stelle aktualisiert, können sie in flachen Dateien anstelle von komplizierten B-Bäumen gespeichert werden. Zum schnellen Abrufen enthält der Wörterbuchindex Offsets in der Wörterbuchdatei, und das Wörterbuch enthält Offsets in der Buchungsdatei. Lucene implementiert auch eine Reihe von Tricks, um das Wörterbuch zu komprimieren und Dateien zu veröffentlichen - wodurch die Festplatten-E / A reduziert werden - ohne dass ein erheblicher CPU-Overhead entsteht.

Suchmaschinen auswerten

Andere weit verbreitete Open-Source-Suchmaschinen sind Swish-E, Glimpse, libibex, freeWAIS und iSearch. Wie jedes Softwarepaket ist jedes für den Einsatz in bestimmten Situationen optimiert. Es ist oft schwierig, diese Tools außerhalb der vorgesehenen Domänen bereitzustellen. Berücksichtigen Sie bei der Bewertung einer Suchmaschine die folgenden Funktionen:

  • Inkrementelle versus Batch-Indizierung: Einige Suchmaschinen unterstützen nur die Batch-Indizierung. Sobald sie einen Index für eine Reihe von Dokumenten erstellt haben, wird das Hinzufügen neuer Dokumente schwierig, ohne dass alle Dokumente neu indiziert werden müssen. Die inkrementelle Indizierung ermöglicht das einfache Hinzufügen von Dokumenten zu einem vorhandenen Index. Für einige Anwendungen, z. B. für Anwendungen, die Live-Datenfeeds verarbeiten, ist die inkrementelle Indizierung von entscheidender Bedeutung. Lucene unterstützt beide Arten der Indizierung.
  • Datenquellen: Viele Suchmaschinen können nur Dateien oder Webseiten indizieren. Dies beeinträchtigt Anwendungen, bei denen indizierte Daten aus einer Datenbank stammen oder bei denen mehrere virtuelle Dokumente in einer einzigen Datei vorhanden sind, z. B. ein ZIP-Archiv. Mit Lucene können Entwickler das Dokument über ein Stringoder ein an den Indexer senden InputStream, sodass die Datenquelle von den Daten abstrahiert werden kann. Bei diesem Ansatz muss der Entwickler jedoch die entsprechenden Lesegeräte für die Daten bereitstellen.
  • Indizierungskontrolle: Einige Suchmaschinen können automatisch durch einen Verzeichnisbaum oder eine Website crawlen, um zu indizierende Dokumente zu finden. Dies ist zwar praktisch, wenn Ihre Daten bereits auf diese Weise gespeichert sind, Crawler-basierte Indexer bieten jedoch häufig eine begrenzte Flexibilität für Anwendungen, die eine differenzierte Kontrolle über die indizierten Dokumente erfordern. Da Lucene hauptsächlich im inkrementellen Modus arbeitet, kann die Anwendung Dokumente suchen und abrufen.
  • Dateiformate: Einige Suchmaschinen können nur Text- oder HTML-Dokumente indizieren. andere unterstützen einen Filtermechanismus, der eine einfache Alternative zum Indizieren von Textverarbeitungsdokumenten, SGML-Dokumenten und anderen Dateiformaten bietet. Lucene unterstützt einen solchen Mechanismus.
  • Inhaltskennzeichnung: Einige Suchmaschinen behandeln ein Dokument als einen einzigen Token-Stream. andere ermöglichen die Angabe mehrerer Datenfelder innerhalb eines Dokuments, z. B. "Betreff", "Zusammenfassung", "Autor" und "Text". Dies ermöglicht semantisch umfangreichere Abfragen wie "Autor enthält Hamilton UND Körper enthält Verfassung". Lucene unterstützt das Markieren von Inhalten, indem Dokumente als Sammlungen von Feldern behandelt werden, und unterstützt Abfragen, die angeben, welche Felder durchsucht werden sollen.
  • Stopp-Textverarbeitung : Gängige Wörter wie "a", "und" und "the" verleihen einem Suchindex nur einen geringen Wert. Da diese Wörter jedoch so häufig vorkommen, trägt ihre Katalogisierung erheblich zur Indizierungszeit und Indexgröße bei. Die meisten Suchmaschinen indizieren bestimmte Wörter, sogenannte Stoppwörter, nicht. Einige verwenden eine Liste von Stoppwörtern, während andere Stoppwörter statistisch auswählen. Lucene behandelt Stoppwörter mit dem allgemeineren AnalyzerMechanismus, der später beschrieben wird, und stellt die StopAnalyzerKlasse bereit , die Stoppwörter aus dem Eingabestream entfernt.
  • Stemming: Oft möchte ein Benutzer eine Abfrage für ein Wort, um mit anderen ähnlichen Wörtern übereinzustimmen. Beispielsweise sollte eine Abfrage nach "Sprung" wahrscheinlich auch mit den Wörtern "gesprungen", "Springer" oder "Sprünge" übereinstimmen. Das Reduzieren eines Wortes auf seine Wurzelform wird als Stemming bezeichnet . Lucene implementiert noch kein Stemming, aber Sie können leicht einen Stemmer durch eine anspruchsvollere AnalyzerKlasse hinzufügen .
  • Abfragefunktionen : Suchmaschinen unterstützen eine Vielzahl von Abfragefunktionen. Einige unterstützen vollständige boolesche Abfragen. andere unterstützen nur und Fragen. Einige geben bei jedem Treffer eine "Relevanz" -Wertung zurück. Einige können Adjazenz- oder Näherungsabfragen bearbeiten - "Suche gefolgt von Suchmaschine " oder "Knicks in der Nähe von Celtics" - andere können nur nach einzelnen Schlüsselwörtern suchen. Einige können mehrere Indizes gleichzeitig durchsuchen und die Ergebnisse zusammenführen, um eine aussagekräftige Relevanzbewertung zu erhalten. Lucene unterstützt eine Vielzahl von Abfragefunktionen, einschließlich aller oben aufgeführten. Lucene unterstützt jedoch nicht die wertvolle Soundex- oder "Klingt nach" -Abfrage.
  • Parallelität: Können mehrere Benutzer gleichzeitig einen Index durchsuchen? Kann ein Benutzer einen Index durchsuchen, während ein anderer ihn aktualisiert? Mit Lucene können Benutzer einen Index transaktional durchsuchen, auch wenn ein anderer Benutzer gleichzeitig den Index aktualisiert.
  • Nicht-englische Unterstützung: Viele Suchmaschinen gehen implizit davon aus, dass Englisch die Zielsprache ist. Dies zeigt sich in Bereichen wie Stoppwortlisten, Stemming-Algorithmen und der Verwendung der Nähe zum Abgleichen von Phrasenabfragen. Da Lucene den Eingabestream über die Analyzervom Entwickler bereitgestellte Klasse vorverarbeitet , ist es möglich, eine sprachspezifische Filterung durchzuführen.

Die obige Liste ist zwar keineswegs erschöpfend, bietet jedoch einen Ausgangspunkt für die Bewertung einer Suchmaschine für ein bestimmtes Projekt. Einige Suchwerkzeuge eignen sich schlecht für bestimmte Aufgaben. Wenn Sie die Anforderungen Ihrer Anwendung kennen, können Sie das richtige Werkzeug für den Job auswählen.

Mit Lucene

Ich werde veranschaulichen, wie Lucene zum Erstellen, Auffüllen und Durchsuchen eines Index verwendet wird. Aus Gründen der Übersichtlichkeit wurden Importanweisungen und Ausnahmebehandlungen in den Beispielprogrammen weggelassen. In diesen Abbildungen habe ich den Suchindex im Dateisystem gespeichert (Sie können Indizes überall speichern, z. B. im Speicher oder in einer Datenbank). Die zu indizierenden Dateien sind einfache Textdateien. Mit Lucene können Sie auch problemlos andere Dokumentformate und Dokumente indizieren, die nicht in Dateien gespeichert sind.

Erstellen Sie einen 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