Vorwort: wieso ein Blog zu PHP, Solr und Lucene?

Wieso ein Blog zu PHP, Solr und Lucene?
Gegenstand und Ausgangspunkt all unserer Aktivitäten auf diesem Gebiet war ein Projekt um ein Nachrichtenportal und die Aufgabe, Recherchen und Analysen im Nachrichtenbestand von über 10 Million News performant zu handeln. Die MySQL Volltextsuche kam da schnell an Ihre grenzen, Oracle war keine Alternative.
Es reifte also die Frage, wie können andere (etwa die Internetsuchmaschiene google) immense Datenmengen spielend handeln?
Wir lösten den MySQL volltext mit Lucene ab. Der Performancegewinn war dramatisch. Suchen im Datenbestand, die vorher über 10 Sekunden dauerten, brauchen mittels Lucene und Solr nur selten mehr als 20ms!
Eine neue Welt tat sich auf, die es zu erobern galt und schnell fiel auf, dass deutschsprachige Seiten zum Thema Mangelware sind. Dies soll sich mit diesem Blog ein wenig ändern.

Sie haben Fragen zu Solr/Lucene/PHP? Schreiben sie uns einen Kommentar!

Montag, 24. September 2012

SolrCloud Grundlagen

Mit wachsendem Datenbestand und mit der wachsenden Verbreitung einer Anwendung werden 2 Faktoren immer wichtiger: Performance und Ausfallsicherheit. Solr bot dafür bisher (und noch immer) Solr Distributed Search und Solr Replication. Nimmt man beide Features zusammen und packt noch etwas Konfigurationsmanagment hinzu, erhält man in etwa das, was Solr Cloud ausmacht.
Früher hätte man es einfach Solr Cluster genannt, heute heißt es dann natürlich Cloud. SolrCloud!
Vorab ein paar Einschränkungen / wichtige Punkte / Probleme zu Solr Cloud:

Solr Probleme mit Umlauten

Während Lucene eine Java Bibliothek ist, ist Solr die Java Anwendung, die diese Bibliothek nutzt. Wie für jede Java Anwendung wird auch für Solr eine Laufzeitumgebung benötigt.
Idealer Weise gibt es seit einigen Versionen von Solr beim offiziellen Download eine All-in-one Variante.
Darin werden geliefert: sämtliche Bibliothken, die man für besondere Solr Funktionen (Clustering, Dataimport Handler, Velocity, ...) benötigt, die Solr Anwendung selber und Jetty. Jetty ist ein kleiner Java Anwendungsserver, in dessen man die Solr Anwendung deployen, also installieren & laufen lassen kann.
Das funktioniert in aller Regel super...
...so lange man nicht versucht, deutsche Umlaute, also äöü und ß zu verarbeiten.

Freitag, 14. September 2012

mehere Solr Suchen / Abfragen in einem Request / URL Aufruf

Bei der Arbeit mit Solr /Lucene ergibt sich oft die Anforderung, dass für mehrere Suchbegriffe eine Solr Abfrage ausgelöst werden muss. Oftmals ändern sich dabei noch nicht einmal die FilterQuery Parameter, sondern lediglich der Suchbegriff. Jede Suchanfrage beginnt dabei mit dem Verbindungsaufbei vom Client / Applikation zum Solr Server. Es läppern sich Latzenzzeiten und Overhead. Die Frage ist also: Kann man in einem einzelnen Solr Request mehrere Suchen verarbeiten / durchführen?
Ja.

Dienstag, 14. August 2012

Unicode Collation: eigene UmwandlungsRollen erstellen

Es gibt in Solr / Lucene immer wieder die Situation, dass zu indizierender Text umgewandelt werden muss. Beispielsweise hinsichtlich von Umlauten in der deutschen Sprache oder andere sprachspezifische Sonderzeichen. Auch die Umwandlung von Abkürzungen in oder aus Sonderzeichen ginge: beispielsweise ä <-> ae oder € <-> EUR oder GPB <-> £ und so weiter.

Dafür kann Unicode Collation zum Einsatz kommen, wie in diesem Artikel bereits beschrieben.

Dafür benötigt man eine entsprechende Datei mit den Definitionen der UmwandlungsRollen. Diese Datei, wir nennen sie customRolles.bin, können wir durch ein kleines Java Tool erstellen.
Dazu folgendes Java Progrämmchen erstellen/anpassen:

Freitag, 20. Juli 2012

Gruppierung (Clustering), clusteringComponent konfiguration und installation

Was bedeutet Clustering

Eins vorab: wir sprechen hier nicht von Hochverfügbarkeit. Dies ist ein komplett anderes Thema, siehe SolrCloud.
Im vorliegenden Fall geht es eher um die semantische, inhaltliche Analyse von Dokumenten und deren Gruppierung:
Bei großen Datenmengen besteht oft der Bedarf, diese in Gruppen zusammenzufassen.
In unserem Beispiel geht es um ein Nachrichtensystem mit tausenden News täglich. Viel zu viel für einen Menschen. Möchte man diese Dokumente aufbereiten, so empfiehlt es sich, diese zu gruppieren. Etwa: alle Nachrichten zum Bereich Wirtschaft, Bereich Politik oder auch Thematisch: alle Nachrichten zur Bundestagswahl oder zu Fußballthema.
Jede dieser Gruppen nennt man Cluster (bestehend aus einzelnen Dokumenten).
Dabei ergeben sich folgende Fragen:
Wie erkenne ich, welche Dokumente zu einer Gruppe (einem Cluster) gehören?
Welchen Namen gebe ich letztlich der Gruppe an Dokumenten?
Bei diesen Fragen hilft uns ein Produkt sehr weiter: Carrot²

Seit Solr 3.1 ist Carrot integriert. Man spricht hier von ClusteringComponent. Aber auch mit älteren Solr Versionen kann man Carrot nutzen.

Montag, 24. Oktober 2011

Solr: Konvertirung von Umlauten: ae<->ä, oe< ->ö, ue <->ü (Unicode Collation)

Kürzlich erhielt ich einige Millionen Dokumente aus längst vergangenen Zeiten, die es zu indizieren galt. Das Problem dabei ist, dass ein Teil der Dokumente aus jener Zeit ist, in der deutsche Umlaute, als ö,ä,ü und ß  in der IT noch kein Thema waren.
Diese Umlaute wurden folglich umschrieben: oe statt ö, ue statt ü, ae statt ä und ss statt ß.

Umlaute mittels Lucene/Solr zu finden ist kein Problem. Ebenso lassen sich natürlich Umschriebene umlaute genauso finden.
Auf der anderen Seite kann man dem User nicht zumuten 2 Suchen abzufeuern, beispielsweise eine nach Schröder und eine nach Schroeder.

Ziel ist es also Solr so zu konfigurieren, dass Suchen nach Schröder auch Schroeder findet. Konkret, dass die Suche nach Wörtern mit  ü,ö,ä auch Wörter findet, die ein ue, oe,ae enthalten, dass Umlaute also konvertiert werden.

Freitag, 23. September 2011

OutOfMemoryException während der Index-Optimierung

Wir sind neulich auf ein interessantes Problem gestoßen:
Unser Index hatte eine Größe erreicht, bei der ein Optimize zu einer OutOfMemoryException führte.
Der wesentliche Teil der Catalina.out gab dabei Folgendes aus:


Caused by: java.lang.OutOfMemoryError: Map failed
>>>        at sun.nio.ch.FileChannelImpl.map0(Native Method)
>>>        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:762)

Als ersten Versuch haben wir den RAM für die JVM höher gesetzt, allerdings mit dem zunächst verwirrenden Ergebnis, dass die OOE noch schneller geworfen wurde als zuvor.

Nach etwas Recherche ließ sich feststellen, dass die nio-Klasse außerhalb des Speichers der JVM wildert und folgedessen eine entsprechende Erhöhung eher Kontraproduktiv ist, da der nun von der JVM zusätzlich verwendete Speicher dem OS und damit der bio-Klasse fehlt. 

Letztendlich lässt sich das Problem einfach in den Griff bekommen. Man muss lediglich der Shell, in welcher die JVM läuft, per 'ulimit -v unlimited' genügend virtuellen Speicher zur Verfügung stellen. Normalerweise sollte es reichen, den ulimit-Befehl in jenes Init-Skript zu schreiben, mit welchem man die JVM, den Tomcat, Jetty - was auch immer - startet.

Wenn man wissen möchte, wie hoch der zur Verfügung stehende virtuelle Speicher von Hause aus ist, dann hilft ein 'ulimit -v'. Und man darf sich nicht täuschen lassen - wir hatten einen Vmem von ~14GB und unser Index hatte "nur" 5GB. Das sollte locker ausreichen, möchte man meinen. Tat es aber nicht. Bei einem Optimize landet man sehr schnell bei sehr hohem Speicherverbrauch.


Entscheidend ist, dass der ulimit-Befehl in jener Shell ausgeführt wird, in welcher die JVM läuft, denn ulimit scheint per se nur in der Shell zu gelten, in welcher er ausgeführt wurde.