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. 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.


Natürlich können so auch Fehler entstehen, bei der Suche nach einem Gärter würde ich in dem Fall auch die Frau Gaertner finden, auch wenn "die richtige Schreibweise ihres Namens gar kein ä vorsieht. Eine Suche nach dem falsch geschriebenen  Göthe bringt dann aber auch den richtgen Goethe als Treffer.
Die ist aber immer noch besser, als Millionen von Dokumente per Hand durchzuschauen, die "richtigen" ae, oe, ue aufzufinden und zu ersetzen.

Bei diesem Vorhaben, der Konvertierung von Umlauten hilft uns die Solr Funktion Unicode Collation.
Ursprünglich dazu gedacht, dass Text nach landesspezifischen Vorgaben sortiert wird, ä also  wie ae einsortiert wird und nicht am Ende des Alphabets, weil die Maschine nicht weiß, wohin damit.

Solr / Lucene greift für landesspezifischen Support gerne auf vorhandene Javabibliotheken zurück. Diese allerdings beantworten offensichtlich nicht die Frage, wie Umlate beim Sortieren behandelt werden soll.
Für Solr muss daher eine Rollendefinition erstellt werden, in der einerseits die vorhandenen, länderspezifische Sortierregeln berücksichtigt werden sowie zusätzlich die Umlaute analog ihrer Umschreibeung.
Diese Rollendefinition, verpackt in einer Datei wird dann Solr bereitgestellt.

Die Solr Dokumentation biete zur Erstellung der Rollendatei (customRules.bin) einen Schnippsel Javacode. Wer aber des Java nicht mächtig ist, weiß diesen Code in aller Regel nicht adäquat zu nutzen. Um den Lesern dises Blogs, die Eröffnung einer neuen Baustelle zu ersparen, kann die fertige customRules.bin hier heruntergeladen werden.
Wer genau wissen möchte, wie eine solche Datei erstellt wird, schaut bitte hier: erstellen der customRoles.bin

Nun muss die customRules.bin noch auf dem Solr Server abgelegt werden und die Felddefinition in der schema.xml entsprechend angepasst werden, in dem man den Unicode Collation Filter hinzufügt:

    <filter class="solr.CollationKeyFilterFactory"
        custom="customRules.bin"
        strength="primary"
    />

Dabei sind 2 Dinge zu beachten:
  1. Der Collation Filter ist im Analyseblock der Felddefinition einzusetzen - zur Query-Zeit sowie ebenfalls zur Index-Zeit (sofern man in der Felddefinition zwischen Query & Index unterscheidet).
  2. Der Term darf durch andere Filter nicht mehr geteilt werden. Dies betrifft insbesondere die WordDelimiterFilterFactory, welche zur Zerlegung von Termen (Wi-Fi nach Wi & Fi) genutzt wird. Hinsichtlich der Reihenfolge der Filter in der schema.xml kommt die WordDelimiterFilterFactory also vor der CollationKeyFilterFactory.

Abschließend ist ein Neuaufbau des Index notwendig, welcher nun leider etwas langsamer vonstatten geht.

5 Kommentare:

  1. Hallo,
    gibts auch eine customRules.bin mit dem polnischen L? (Ł/ł)
    Ansonsten alles TOP.
    Funktioniert super!

    AntwortenLöschen
    Antworten
    1. Hallo,
      eine fertige customRules.bin für polnisch habe ich nicht, aber diese kann man sich auch selber bauen.
      http://wiki.apache.org/solr/UnicodeCollation#ICU_Collation
      in Verbindungmit:
      http://java.sun.com/j2se/1.5.0/docs/api/java/text/RuleBasedCollator.html
      Das grundsätzliche Vorgehen ist wie folgt:

      1.) Javacode anpassen
      2.) Javacode ausführen und customRules.bin erzeugen lassen
      3.) customRules.bin wie oben gezeigt einbinden

      Ich werde die Tage mal einen Blog Eintrag dazu veröffentlichen. Wichtig wäre dazu die Übersetzung der polnischen Buchstaben: was wird normalerweise wie umschrieben. Wenn ich das bekommen könnte, könnte ich gleich die polnische Version versuchen.

      Gruß, Thx

      Löschen
    2. so, ich habe dann mal einen Blog Artikel dazu geschrieben:
      http://php-solr-lucene.blogspot.de/2012/08/unicode-collation-eigene.html

      Löschen
  2. Vielen Dank. Funktioniert wunderbar.
    Nur hab ich jetzt das Problem das die Wildcardsuche nicht mehr funktioniert. Gibt es einen weg beides wieder zum laufen zu bekommen?

    Mein fieldType sieht folgendermaßen aus:
    http://pastebin.com/chYgqBkS

    AntwortenLöschen
    Antworten
    1. Hallo,
      die Wildcardsuche sollte davon unberührt bleiben. Zumindest die "Rechtstrunkierung". Also die Suche nach bspw. "Such*" für "Suchmaschine", "Suchergebnis", "Suchgeschwindigkeit". Die Linkstrunkierung, also "*maschine" funktioniert in Solr ohnehin nicht ad hoc. Dazu ist ein Reverse-Feld notwendig. Im geposteten Code kann ich erstmal keinen Fehler erkennen, warum die Platzhaltersuche nicht funktionieren sollte.
      Besteht das Problem noch?

      Löschen