Apache Lucene 4.0

API-Kompatibilität

Durch die vielen Änderungen unter anderem im Codec-Backend war es nötig, die API an zahlreichen Stellen anzupassen. Die Änderungen sind so groß, dass eine Rückwärts-Kompatibilität zu alten Code nicht mehr gewahrt werden konnte. Der Umstieg auf Lucene 4.0 ist also nicht durch simples Ersetzen der JAR-Dateien und Rekompilierung des Codes erreichbar. Es müssen zahlreiche Anpassungen durchgeführt werden, aber auch viele „alte“ Konzepte neu überdacht werden, da manche Algorithmen mit der neuen API nicht mehr genauso wie vorher umsetzbar sind. Dies wird einige Programmierer vor eine schwierige Aufgabe stellen, sollte aber mit Hilfe der mitgelieferten Dokumentation [7] und dem darin enthaltenen „Migration Guide“ gut durchführbar sein. Folgende Änderungen werden die meisten Benutzer betreffen:

Die Klassenstruktur für Dokumente und Ihre Felder, wie sie beim Indexieren und Darstellen von Suchresultaten verwendet werden, wurde modernisiert, indem eine zusätzlicher „FieldType“ eingefügt wurde, der die Eigenschaften der Felder eines Dokuments festlegt (analysierter Text, Keywords, numerische Werte; indexiert, gespeichert oder die neue Variante DocValues). Für Version 5.0 von Lucene sind hier weitere Anpassungen geplant, wie die komplette Trennung von Dokument-Instanzen, die in den Inverted Index aufgenommen werden (indexed), und solche, welche zur Darstellung von Suchergebnissen benutzt werden (stored).

Bereits seit Version 2.9/3.0 wird die Suche von Lucene nun nicht mehr auf dem gesamten Index ausgeführt, sondern jedes Index-Segment wird separat behandelt. Es war aber trotzdem in der 3.x-Serie noch möglich, Suchanfragen mit dem IndexReader auszuführen, wobei dieser die TermEnums der einzelnen Segmente on-the-fly als eine verfügbar machte. In ganz alten Lucene-Versionen war dies immer der Fall, so dass häufig empfohlen wurde, einen Index zu optimieren, so dass er auf ein Segment zusammengeführt wird. Durch die „Per-Segment-Search“ ist schon für die ganze 3.x-Versions-Serie eine Index-Optimierung in den meisten Fällen überflüssig und bereits in Version 3.5 die zugehörige Methode in der IndexWriter Klasse deprecated.

Lucene 4.0 treibt das weiter und erwartet von jeder Lucene-Implementierung, dass sie nur noch auf den einzelnen Segmenten arbeitet. Um dies zu erreichen, wurde das ehemalige IndexReader interface in mehrere Typen aufgespalten. IndexReader ist nur noch mit den nötigsten Funktionen ausgestattet, um z.B. nach einer Suche die Suchergebnisse darzustellen, er bietet allerdings keinen Zugriff mehr auf das Term-Dictionary oder die Postings. Die zwei neuen Subklassen CompositeReader und AtomicReader sind nun mit abstrakten Methoden ausgestattet, die für diese zwei IndexReader-Varianten spezifische Funktionen bereitstellen:

  • AtomicReader ist nun das eigentliche Herzstück der Lucene-Suche, denn nur diese Klasse bietet Zugriff auf das Term-Dictionary und die Postings. Dazu exportiert es die neue Klasse Fields, die direkt vom Codec implementiert wird. Mit Hilfe von Fields kann man auf das Term Dictionary zugreifen (Terms, TermsEnum) oder die Postings für einen Term abrufen (DocsEnum, DocsAndPositionsEnum). In der Praxis wird die AtomicReader-API von der internen Klasse SegmentReader bereitgestellt, welche die einzelnen Segmente des Indexes abbildet. Die meisten Funktionen hierin werden durch das für dieses Segment zuständige Codec zur Verfügung gestellt.
  • CompositeReader ist lediglich eine Collection aus anderen IndexReadern (CompositeReaders oder AtomicReaders), die zusammen einen kompletten Index abbilden. Da es sich lediglich um eine „Collection“ handelt, hat man über diese Klasse keinerlei Zugriff auf das Term Dictionary oder die Postings. Es werden lediglich die Methoden aus IndexReader zum Zugriff auf Stored Fields, die zur Anzeige von Suchergebnissen nötig sind, bereitgestellt. Um jetzt eine Suche durchzuführen, die ein Term Dictionary und Postings benötigt, kann man mit der Methode leaves() alle „Blätter“, die AtomicReader dieser Collection, erhalten. Man erhält dabei eine sortierte Liste der neuen Klasse AtomicReaderContext zurück, die eine Referenz zum AtomicReader und die docBase (Offset der ersten Dokument-ID im ID-Raum des CompositeReader) zurückliefert. Für einfache Suchabfragen muss man jedoch nicht diesen Aufwand treiben: Die bereits aus vorherigen Versionen von Lucene bekannte Klasse IndexSearcher verwendet genau diese Vorgehensweise, um ein Query auf allen Blättern (den Indexsegmenten) auszuführen.

Die dritte abstrakte Klasse in dieser Reihe ist ein Spezialfall von CompositeReader, nämlich DirectoryReader: Diese Klasse wird am meisten verwendet, denn sie ist der zentrale Einstiegpunkt, um auf einen Index auf dem Speichermedium zuzugreifen: Die früher direkt in der Klasse IndexReader vorhandenen statischen Factory-Methoden open() und openIfChanged() sind jetzt hier angesiedelt und liefern konkrete Instanzen vom abstrakten DirectoryReader zurück. Daneben gibt es Methoden zum Abfragen der Index Metadaten wie die Versionsnummer, eventuell vorhandene Commit-Points, und ob die aktuelle Instanz auf dem neuesten Stand ist und eventuell ein openIfChanged() nötig ist.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.