Social Software powered by Instant Communities
Springe direkt: zur Navigationzum Inhaltzur Sidebar
Jul10

Zend_Search_Lucene und Symfony – Teil 1

gepostet von Johannes Schmidt

Mit Zend_Search_Lucene als Teil des Open Source Frameworks von Zend steht für PHP5 eine Index-basierte Textsuche zur Verfügung. Zend_Search_Lucene ist abgeleitet vom Apache Lucene Projekt. Die Indexdateiformate sind mit Apache Lucene Version >1.4 kompatibel.

Lucene bzw. dessen Indexdateiformat unterstützt keine Aktualisierung von Dokumenten. Will man ein document bzw. enthaltene Daten aktualisieren, muss das betreffende document erst gelöscht und dann mit den neuen Daten wieder indexiert werden. Ohne (regelmäßige) Optimierung des Indexes über $index->optimize() fragmentiert so der Index, was zu Einbußen in der Performance führt. Es empfiehlt sich zudem, den Abschnitt im Zend-Manual zur automatischen Indexoptimierung zu lesen.

UTF-8 wird von Zend_Search_Lucene unterstützt, jedoch werden die Daten case-sensitive behandelt.

Die Integration von Zend_Search_Lucene in das PHP-Framework Symfony, siehe auch der Artikel von Andreas Stephan, ist sehr einfach, wählt man den Weg, den Peter Van Garderen beschreibt. Nach dem Kopieren der benötigten Klassen in den lib-Ordner des jeweiligen Symfony-Projektes steht Lucene global in der Applikation zur Verfügung. Es bietet sich natürlich an, eine Klasse, welche die Funktionalität zur Bearbeitung des Indexes und zur Suche bereitstellt, ebenfalls in lib anzulegen. Die Erstellung eines Indexes ist simpel:

$index = Zend_Search_Lucene::create(self::getIndexLocation($indexName));

In diesem Beispiel können über getIndexLocation($indexName) an mehreren definierten Zielorten auf dem Server Indexe erstellt und angesprochen werden.

Der Index soll UTF-8 kodiert werden. Hierfür stellt Zend_Search_Lucene einen entsprechenden Analyzer zur Verfügung, der explizit vor dem Indexieren und einer Suchanfrage gesetzt wird:

Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num(), new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num());

Diesen Aufruf habe ich in einer Funktion setIndexAnalyzer() verpackt.

Wie bereits oben erwähnt, sind diese Daten case-sensitive. Ein Workaround könnte sein, mittels strtolower() alle Indexate zu normieren:

$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Text('username', strtolower($userName), 'utf-8'));
...

Eine Suchanfrage wird dann ebenfalls derart normiert. Viele Nutzer geben ohnehin Suchwörter kleingeschrieben in Suchfelder ein. Problematisch ist dieser Weg natürlich, wenn indexierte Inhalte die Rückgabe selbst sind, bspw. ein Blogartikel. Hier könnte die Lösung sein, eine quasi redundante Struktur anzulegen. Ein field für die Suche und eines für die Rückgabe. Wer auf UTF-8 verzichten kann, der kann natürlich den insensitiven Common Text Analyzer verwenden.

Bei den ersten Gehversuchen mit Zend_Search_Lucene, Version 0.9.3 Beta, haben mir Inkonsistenzen Kopfzerbrechen bereitet. Die Zuweisungen der Terme zu den Dokumenten, in denen sie vorkommen sollten, stimmten häufig nach Schreibzugriffen auf den Index nicht mehr. Die Lösung dieses Problems bestand darin, das Index-Objekt mittels Destruktor explizit frei zu geben. Intern wird hier u. a. für das Index-Objekt commit() und für das Zend_Search_Lucene_Storage_Directory-Objekt close() gerufen. So sieht das Schreiben in den Index bspw. wie folgt aus:

$doc = self::createUserIndexDocument($user); //das document komplett erstellen
$index->addDocument($doc);
$index->__destruct();

Der Index wird in unserem Anwendungsfall inkrementell aufgebaut. Dafür werden zu indexierende Daten in eine Queue geschrieben, die von einem Batch-Script innerhalb des Symfony-Projektes regelmäßig ausgelesen wird. Darüber werde ich in einem zweiten Teil berichten.

5 Antworten

Kommentare zu diesem Beitrag als RSS 2.0 feed.

  • Am July 27th, 2007 schrieb t8d blog » Blog Archiv » Zend_Search_Lucene und Symfony - Teil 2

    [...] Zusätzlich wird der Index in regelmäßigen Intervallen optimiert (siehe auch Teil 1). [...]

  • Am October 5th, 2007 schrieb uli

    vielen dank für den hinweis auf den korrupten index: mit dem problem
    haben wir auch gekämpft.

  • Am October 7th, 2007 schrieb Johannes Schmidt

    Bzgl. UTF-8 sei noch erwähnt, dass erst ein expl. “setlocale(‘LC_ALL’, ‘de_DE.UTF-8′)” vor der Erstellung der docs die gewünschte Portabilität des Codes auf verschiedene Server garantiert.

  • Am October 12th, 2007 schrieb Symfony - Eine Volltextsuche muss her! | ausgebloggt.de

    [...] zum Plugin, in dessen Beschreibung ausdrücklich auf das Alpha Stadium hingewiesen wird, ist die manuelle Integration der Klasse aus dem Zend Framework. Den Weg dazu beschreibt Johannes Schmidt… oder auch hier Dave Dash auf Englisch. Wohl der zuverlässigere Weg, mit dem ich mich auch noch [...]

  • Am February 10th, 2011 schrieb Simon Diercks

    Schau Dir statt strtolower mal Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive an.

    blessings, sd

Kommentar abgeben

Folgendes HTML ist erlaubt: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

* Pflichtfelder

Creative Commons License
This work is licensed under a
Creative Commons Attribution-Share Alike 2.5 License.
t8d blogged mit WordPress