Einführung in Lucene

Einführung in Lucene
In dieser Lektion werden wir die Arbeitsweise hinter einer der leistungsstärksten Volltext-Suchmaschine, Apache Lucene, verstehen. Mit Apache Lucene können wir die APIs verwenden, die sie in vielen Programmiersprachen aufdeckt und die von uns benötigten Funktionen erstellt. Lucene ist einer der leistungsstärksten Motor, auf dem Elasticsearch aufgebaut ist. Bevor wir mit einer Anwendung beginnen, die die Arbeit von Apache Lucene demonstriert, werden wir verstehen, wie Lucene funktioniert und viele seiner Komponenten. Lass uns anfangen.

Warum wird Lucene benötigt??

Die Suche ist eine der häufigsten Operationen, die wir mehrmals am Tag ausführen. Diese Suche kann über mehrere Webseiten auf dem Web oder einer Musikanwendung oder einem Code-Repository oder einer Kombination aus allen vorhanden sein. Man könnte denken, dass eine einfache relationale Datenbank auch die Suche unterstützen kann. Das ist richtig. Datenbanken wie MySQL unterstützen die Volltext-Suche. Aber was ist mit dem Web, einer Musikanwendung oder einem Code -Repository oder einer Kombination aus all diesen? Die Datenbank kann diese Daten nicht in ihren Spalten speichern. Selbst wenn dies der Fall war, wird es inakzeptabel Zeit, die Suche so groß durchzuführen.

Eine Volltext-Suchmaschine kann eine Suchabfrage auf Millionen von Dateien gleichzeitig ausführen. Die Geschwindigkeit, bei der Daten heute in einer Anwendung gespeichert werden, ist riesig. Das Ausführen der Volltext-Suche in dieser Art von Datenvolumen ist eine schwierige Aufgabe. Dies liegt daran, dass die Informationen, die wir benötigen, in einer einzelnen Datei aus Milliarden von Dateien,.

Wie Lucene funktioniert?

Die offensichtliche Frage, die Ihnen in den Sinn kommen sollte, ist, wie schnell Lucene beim Ausführen von Abfragen "Volltext-Suchanlagen" so schnell ausgeführt wird? Die Antwort darauf ist natürlich mit Hilfe von Indizes, die sie erzeugt. Aber anstatt einen klassischen Index zu erstellen, nutzt Lucene von Umgekehrte Indizes.

In einem klassischen Index sammeln wir für jedes Dokument die vollständige Liste der Wörter oder Begriffe, die das Dokument enthält. In einem umgekehrten Index speichern wir für jedes Wort in allen Dokumenten, in welchem ​​Dokument dieses Wort/die Begriff gefunden werden kann. Dies ist ein hoher Standardalgorithmus, der die Suche sehr einfach macht. Betrachten Sie das folgende Beispiel für das Erstellen eines klassischen Index:

Doc1 -> "this", ",", "einfach", "lucene", "sample", "klassisch", "invertiert", "index"
DOC2 -> "Running", "Elasticsearch", "Ubuntu", "Update"
Doc3 -> "rabbitmq", "lucene", "kafka", "", "fing", "boot"

Wenn wir einen invertierten Index verwenden, haben wir Indizes wie:

This -> (2, 71)
Lucene -> (1, 9), (12,87)
Apache -> (12, 91)
Framework -> (32, 11)

Invertierte Indizes sind viel einfacher zu pflegen. Nehmen wir an, wenn wir Apache in meinen Begriffen finden möchten, werde ich sofort Antworten mit umgekehrten Indizes haben, während mit klassischer Suche in vollständigen Dokumenten ausgeführt wird, die möglicherweise nicht in Echtzeitszenarien ausgeführt werden können.

Lucene Workflow

Bevor Lucene tatsächlich die Daten durchsuchen kann, muss sie Schritte ausführen. Lassen Sie uns diese Schritte visualisieren, um ein besseres Verständnis zu erhalten:

Lucene Workflow

Wie im Diagramm gezeigt, passiert dies in Lucene:

  1. Lucene wird mit den Dokumenten und anderen Datenquellen gefüttert
  2. Für jedes Dokument konvertiert Lucene diese Daten zunächst in Klartext und dann konvertiert die Analysatoren diese Quelle in Klartext
  3. Für jeden Begriff im einfachen Text werden die umgekehrten Indizes erstellt
  4. Die Indizes sind bereit, durchsucht zu werden

Mit diesem Workflow ist Lucene eine sehr starke Volltext-Suchmaschine. Aber dies ist der einzige Teil, der Lucene erfüllt. Wir müssen die Arbeit selbst ausführen. Schauen wir uns die Komponenten der erforderlichen Indexierung an.

Lucene -Komponenten

In diesem Abschnitt werden wir die grundlegenden Komponenten und die grundlegenden Lucene -Klassen beschreiben, die zum Erstellen von Indizes verwendet werden:

  • Verzeichnisse: Ein Lucene -Index speichert Daten in normalem Dateisystem Directoies oder in Speicher, wenn Sie mehr Leistung benötigen. Es ist vollständig die Apps -Auswahl, Daten zu speichern, wo immer sie möchten, eine Datenbank, den RAM oder die Festplatte.
  • Unterlagen: Die Daten, die wir an die Lucene-Engine füttern, müssen in Plain-Text umgewandelt werden. Dazu erstellen wir ein Dokumentobjekt, das diese Datenquelle darstellt. Später, wenn wir eine Suchabfrage ausführen, erhalten wir daher eine Liste von Dokumentobjekten, die die von uns bestandene Abfrage erfüllen.
  • Felder: Dokumente sind mit einer Sammlung von Feldern besiedelt. Ein Feld ist einfach ein Paar (Name, Wert) Artikel. Während wir also ein neues Dokumentobjekt erstellen, müssen wir es mit solchen gepaarten Daten füllen. Wenn ein Feld invertlich indiziert wird, ist der Wert des Feldes tokenisiert und steht zur Suche zur Verfügung. Während wir Felder verwenden, ist es nicht wichtig, das tatsächliche Paar zu speichern, sondern nur das invertierte indizierte. Auf diese Weise können wir entscheiden, welche Daten nur durchsuchbar sind und nicht wichtig sind, um gespeichert zu werden. Schauen wir uns ein Beispiel hier an:

    Feldindexierung

    In der obigen Tabelle haben wir beschlossen, einige Felder aufzubewahren, und andere werden nicht gespeichert. Das Körperfeld wird nicht gespeichert, sondern indiziert. Dies bedeutet, dass die E -Mail als Ergebnis zurückgegeben wird, wenn die Abfrage nach einem der Begriffe für den Körperinhalt ausgeführt wird.

  • Bedingungen: Begriffe repräsentieren ein Wort aus dem Text. Begriffe werden aus der Analyse und Tokenisierung der Felderwerte extrahiert Der Begriff ist die kleinste Einheit, auf der die Suche ausgeführt wird.
  • Analysatoren: Ein Analysator ist der wichtigste Teil des Indexierungs- und Suchprozesses. Es ist der Analysator, der den Ebenentext in Token und Begriffe begleitet, damit sie durchsucht werden können. Nun, das ist nicht die einzige Verantwortung eines Analysators. Ein Analysator verwendet einen Tokenizer, um Token zu machen. Ein Analysator erledigt auch die folgenden Aufgaben:
    • Stemming: Ein Analysator verwandelt das Wort in einen Stamm. Dies bedeutet, dass „Blumen“ in das Stammwort 'Blume' umgewandelt werden. Wenn also eine Suche nach "Blume" ausgeführt wird, wird das Dokument zurückgegeben.
    • Filterung: Ein Analysator filtert auch die Stoppwörter wie "Das", "ist" usw. Da diese Wörter keine Fragen zum Ausführen anziehen und nicht produktiv sind.
    • Normalisierung: Dieser Prozess beseitigt Akzente und andere Charaktermarkierungen.

    Dies liegt nur in der normalen Verantwortung von StandardAnalyzer.

Beispielanwendung

Wir werden eines der vielen Maven -Archetypen verwenden, um ein Beispielprojekt für unser Beispiel zu erstellen. Um das Projekt zu erstellen, führen Sie den folgenden Befehl in einem Verzeichnis aus, den Sie als Arbeitsbereich verwenden werden:

MVN -Archetyp: generieren -dgroupid = com.LinuxHint.Beispiel -dartifactid = lh -lucenexample -darchetypeartifactid = maven -archetyp -quickstart -dinteractivemode = false

Wenn Sie Maven zum ersten Mal ausführen, dauert es einige Sekunden, um den Befehl generieren. So sieht die Projektausgabe aus:

Projektaufbau

Sobald Sie das Projekt erstellt haben, können Sie es in Ihrer Lieblings -IDE öffnen. Der nächste Schritt besteht darin, dem Projekt geeignete Maven -Abhängigkeiten hinzuzufügen. Hier ist der Pom.XML -Datei mit den entsprechenden Abhängigkeiten:



Org.Apache.Lucene
Lucene-Core
4.6.0


Org.Apache.Lucene
Lucene-Analyzers-Common
4.6.0

Um alle Gläser zu verstehen, die dem Projekt hinzugefügt werden, wenn wir diese Abhängigkeit hinzugefügt haben. Hier ist ein Befehl, den wir verwenden können:

MVN -Abhängigkeit: Baum

Wenn wir diesen Befehl ausführen, werden uns der folgende Abhängigkeitsbaum angezeigt:

Schließlich erstellen wir eine SimpleIndexer -Klasse, die ausgeführt wird

Paket com.LinuxHint.Beispiel;
Java importieren.io.Datei;
Java importieren.io.Filerader;
Java importieren.io.IoException;
import org.Apache.Lucene.Analyse.Analysator;
import org.Apache.Lucene.Analyse.Standard.StandardAnalyzer;
import org.Apache.Lucene.dokumentieren.Dokumentieren;
import org.Apache.Lucene.dokumentieren.Gelagertes Feld;
import org.Apache.Lucene.dokumentieren.Textfeld;
import org.Apache.Lucene.Index.Indexwriter;
import org.Apache.Lucene.Index.IndexWriterConfig;
import org.Apache.Lucene.speichern.Fsdirectory;
import org.Apache.Lucene.Util.Ausführung;
öffentliche Klasse SimpleIndexer
private statische endgültige String-IndexDirectory = "/user/shubham/irgendwo/lh-lucenexample/index";
private statische endgültige String-DirtobeInedExed = "/user/shubham/irgendwo/lh-lucenexample/src/main/java/com/linuxHint/example";
public static void main (String [] args) löst Ausnahme aus
Datei indexDir = neue Datei (IndexDirectory);
Datei datadir = neue Datei (DirtobeIndexed);
SimpleIndexer Indexer = new SimpleIndexer ();
int numindexed = Indexer.Index (IndexDir, Datadir);
System.aus.println ("Gesamtdateien indiziert" + numindexed);

private int index (Datei indexDir, Datei datadir) löst IOException aus
Analyzer Analyzer = neuer StandardAnalyzer (Version.Lucene_46);
IndexWriterConfig config = new indexWriterConfig (Version.Lucene_46,
Analysator);
Indexwriter IndexWriter = neuer Indexwriter (FSDirectory.Open (Indexdir),
Konfiguration);
Datei [] Dateien = Datadir.listFiles ();
für (Datei f: Dateien)
System.aus.println ("Indexierungsdatei" + F.GetCanonicalPath ());
Document doc = new document ();
Dokument.add (neues Textfeld ("Inhalt", New FileReader (f)));
Dokument.Add (New StoredField ("Dateiname", f.GetCanonicalPath ()));
Indexwriter.adddocument (doc);

int numindexed = IndexWriter.maxdoc ();
Indexwriter.schließen();
Numindexed zurückgeben;

In diesem Code haben wir gerade eine Dokumentinstanz erstellt und ein neues Feld hinzugefügt, das den Dateiinhalt darstellt. Hier ist die Ausgabe, die wir erhalten, wenn wir diese Datei ausführen:

Indexierungsdatei/Benutzer/Shubham/Anwo/lh-lucenexample/src/main/java/com/linuxHint/Beispiel/SimpleIndexer.Java
Gesamtdateien indiziert 1

Außerdem wird im Projekt ein neues Verzeichnis mit folgenden Inhalten erstellt:

Indexdaten

Wir werden analysieren, was alle Dateien in diesem Index in mehr Lektionen auf Lucene erstellt werden.

Abschluss

In dieser Lektion haben wir uns angesehen, wie Apache Lucene funktioniert, und wir haben auch eine einfache Beispielanwendung erstellt, die auf Maven und Java basierte.