2011-01-13 4 views
3

Dies kann als eine allgemeine Java-Frage betrachtet werden, aber zum besseren Verständnis verwende ich Lucene als Beispiel.Der Prozess, den Lucene Text in Tokenize

Sie können verschiedene Tokenizer in Lucene verwenden, um Text zu tokenisieren. Es gibt die abstrakte Haupt-Tokenizer-Klasse und dann viele verschiedene Klassen, die sie erweitern. Das Gleiche gilt für TokenFilter.

Nun scheint es, dass jedes Mal, wenn Sie ein Dokument indizieren möchten, ein neuer Tokenizer erstellt wird. Die Frage ist, da Tokeinzer nur eine Utility-Klasse ist, warum sollte man sie nicht statisch machen? Zum Beispiel kann ein Tokenizer, der alle Buchstaben in Kleinbuchstaben umwandelt, eine statische Methode haben, die genau das für jede Eingabe tut. Was ist der Sinn, ein neues Objekt für jeden zu indexierenden Text zu erstellen?

Eine Sache zu erwähnen - Tokeinzer hat ein privates Feld, das die Eingabe enthält, die es erhält, um Tokenize. Ich sehe nur nicht, warum wir es auf diese Weise speichern müssen, weil das Objekt direkt nach dem Tokenisierungsprozess zerstört wird und der neue Token-Text zurückgegeben wird. Das einzige, woran ich denken kann, ist Multi-Thread-Zugang vielleicht?

Vielen Dank!

Antwort

6

Nun scheint es, dass jedes Mal, wenn Sie indizieren möchten ein Dokument, ein neues Tokenizer

erstellt

Das ist nicht wahr, wird die Analyzer.reusableTokenStream Methode aufgerufen, die wieder verwendet nicht nur ein Tokenizer, aber auch die gesamte Kette (TokenFilters, etc). Siehe http://lucene.apache.org/java/3_0_0/api/core/org/apache/lucene/analysis/Analyzer.html#reusableTokenStream(java.lang.String, java.io.Reader)

Eine Sache zu erwähnen - Tokeinzer verfügt über ein eigenes Feld, das die Eingabe enthält es tokenize empfängt. Ich sehe nur nicht, warum wir es auf diese Weise speichern müssen, weil das Objekt direkt nach dem Tokenisierungsprozess zerstört wird und der neue Token-Text zurückgegeben wird. Das einzige, woran ich denken kann, ist Multi-Thread-Zugang vielleicht?

Wie bereits erwähnt, wird die gesamte Kette von Tokenizern und Tokenfiltern in Dokumenten wiederverwendet. Daher werden alle ihre Attribute wiederverwendet, aber es ist auch wichtig zu beachten, dass Attribute über die Kette verteilt sind (z.B. verweisen alle Tokenizers- und TokenFilters-Attributverweise auf die gleichen Instanzen). Aus diesem Grund ist es wichtig, in Ihrem Tokenizer clearAttributes() aufzurufen, um alle Attribute zurückzusetzen.

Als Beispiel fügt ein Whitespace Tokenizer einen Verweis auf ein TermAttribute in seinem ctor hinzu und wird von einem LowerCaseFilter umschlossen, der ebenfalls einen Verweis auf ein TermAttribute in seinem ctor hinzufügt. Beide TermAttributes zeigen auf das gleiche zugrunde liegende Zeichen []. Wenn ein neues Dokument verarbeitet wird, wird Analyzer.reusableTokenStream aufgerufen, das die gleiche TokenStream-Kette (in diesem Fall Whitespace mit LowerCaseFilter) zurückgibt, die im vorherigen Dokument verwendet wurde. Die Reset-Methode (Reader) wird aufgerufen und setzt die Eingabe des Tokenizers auf den Inhalt des neuen Dokuments zurück. Schließlich wird reset() für den gesamten Stream aufgerufen, der jeden internen Status aus dem vorherigen Dokument zurücksetzt, und der Inhalt wird verarbeitet, bis incrementToken() false zurückgibt.

+0

Vielen Dank. Das macht jetzt sehr viel Sinn. – user431336

0

Machen Sie sich keine Sorgen darüber, hier und da eine Instanz einer Klasse zu erstellen, wenn Sie etwas komplexes wie das Indizieren eines Dokuments mit Lucene tun. Es wird wahrscheinlich viele und viele Objekte innerhalb des Tokenisierungs- und Indizierungsprozesses erstellen. Eine weitere Tokeniser-Instanz ist buchstäblich nichts, wenn der Rest von verworfenen Objekten nach Abschluss des Prozesses verglichen wird. Wenn Sie nicht glauben, dass ich ein Profil erhalte und die Erstellung von Objekten beobachte, zählt.