Blog

Blog

Neues aus unserem Blog

Phonetische Suche mit Solr

Jochen Just Dienstag, 29. Januar 2013 @ 11:51 geschrieben von Jochen Just

Der Einsatz phonetischer Algorithmen kann die Qualität einer Suche je nach Anwendungsfall steigern, besonders wenn Namen im Spiel sind. Auch Solr unterstützt über die PhoneticFilterFactory diese Möglichkeit. Verwendet man den DoubleMetaphone-Algorithmus, finden sich bei einer Suche nach Meier auch die anderen Schreibweisen Meyer, Mayer und Maier.

Auch die Schreibweise spielt keine Rolle. Egal ob groß oder klein geschrieben: müller findet auch Müller.

Ein weiteres großes Plus ist der Umgang mit Umlauten. Eine Suche nach Schuetz findet Schütz. Sucht man nach Strauss, erhält man auch Strauß als Ergebnis zurück.

...
<fieldType name="double_metaphone" class="solr.TextField" sortMissingLast="true">
  <analyzer>
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.PhoneticFilterFactory" encoder="DoubleMetaphone" inject="false"/>
  </analyzer>
</fieldType>
...
<field name="name-double_metaphone" type="double_metaphone" 
       indexed="true" stored="true" required="true" /> 
...

So weit, so gut. Tritt allerdings der Anwendungsfall ein, dass nicht nur Namen, sondern auch andere Eigenschaften einer Person gesucht werden, wie Beruf oder Fähigkeiten, tauchen je nach Größe des Suchkörpers schnell nicht relevante Ergebnisse auf. Eine Suche an Hand des Fields name-double_metaphone für den Begriff Türsteher fände ein Dokument, das den Namen Tristan als Eingabe für dieses Field hat.

Wie kann man diesem Problem entgegenwirken?

Spezieller Algorithmus für die deutsche Sprache

Nach kurzer Recherche stößt man auf einen phonetischen Algorithmus, der speziell auf die deutsche Sprache abzielt: Kölner Phonetik (Der Name mag wohl in die Irre führen, aber er eignet sich tatsächlich für die deutsche Sprache und nicht nur für den rheinischen Dialekt). Einem schnellen Blick in das Solr-Wiki zum Thema PhoneticFilterFactory zu Folge, wird dieser Algorithmus aber nicht von Solr unterstützt.

Wirft man hingegen einen Blick in den Quellcode stellt sich heraus, dass der Algorithmus doch unter dem Namen ColognePhonetic unterstützt wird.

Es können sogar beliebige Algorithmen eingebunden werden. Die beiden Bedingungen dafür sind,

Weitere Details zu diesem Thema kann man dem entsprechenden Solr-Issue entnehmen.

 

Der FieldType und das zugehörige Field, um ColognePhonetik zu verwenden, könnte dann so aussehen:

...
<fieldType name="cologne_phonetic" class="solr.TextField" sortMissingLast="true">
  <analyzer>
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.PhoneticFilterFactory" encoder="ColognePhonetic" inject="false"/>
  </analyzer>
</fieldType>
...
<field name="name-cologne_phonetic" type="cologne_phonetic" 
       indexed="true" stored="true" required="true" />
...

Probleme mit Kölner Phonetik und Solr

Die Arbeitsweise von ColognePhonetic bringt allerdings ein Problem mit sich:

Der Algorithmus wandelt die Zeichen in eine Ziffernfolge um. Die gleiche Ziffernfolge bedeutet gleicher Klang.

Sucht man nun z.B. nach 082 (etwa eine Suche nach Telefonnummern o.ä.) findet man alle Solr-Dokumente, die als Eingabe des Fields name_cologne-phonetic z.B. den Namen Just, Jost usw. haben. Das ist sicherlich nicht das gewünschte Verhalten. Das Problem ist, dass Solr eine Ziffernfolge unverändert übernimmt.

Durch einen kleinen Trick kann man diesen Umstand aber umgehen:

...
<fieldType name="cologne_phonetic-no_digits" class="solr.TextField" sortMissingLast="true">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.PhoneticFilterFactory" encoder="ColognePhonetic" inject="false"/>
  </analyzer>
  <analyzer type="query">
    <charFilter class="PatternReplaceCharFilterFactory" pattern="^(.*)$" replacement="$1#"/>
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.PhoneticFilterFactory" encoder="ColognePhonetic" inject="false"/>
  </analyzer>
</fieldType>
...
<field name="name-cologne_phonetic-no_digits" type="cologne_phonetic-no_digits" 
       indexed="true" stored="true" required="true" /> 
...

Man hängt während der Suchanalyse ein # an das Ende des Suchbegriffs. Dieses Sonderzeichen bewirkt, dass passende alphanummerische Suchbegriffe gefunden werden, aber nummerische Suchbegriffe nicht mehr. D.h. eine Suche nach Jost findet auch Just, eine Suche nach 082 findet Just hingegen nicht mehr.

Beider-Morse-Algorithmus

Seit Solr 3.6 kann man die BeiderMorseFilterFactory einsetzen. Dieser Algorithmus ist auf Nachnamen aus dem zentral- und osteuropäischen Raum ausgelegt. Auf den ersten Blick sind die Ergebnisse recht vielversprechend und vermeiden die oben genannten Probleme.

Praktische Erfahrungen in einem Projekt und somit einem großen Suchkörper habe ich damit noch keine gesammelt.

...
<fieldType name="beider_morse" class="solr.TextField" sortMissingLast="true">
  <analyzer>
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.BeiderMorseFilterFactory" nameType="GENERIC" 
            ruleType="APPROX" concat="true" languageSet="auto"/>
  </analyzer>
</fieldType>
...
<field name="name-beider_morse" >type="beider_morse" 
       indexed="true" stored="true" required="true" />
...

Beispielkonfigurationen

Im Anhang finden Sie ein Archiv, das eine Konfiguration für Solr 3.6.2 und Solr 4.0 enthält, um die angesprochenen Punkte nachzuvollziehen. Im Archiv ist eine Readme.txt enthalten, die die Installation und die Benutzung erklärt.


zur Übersicht

Willkommen auf dem avono Blog

Hier auf dem avono Blog finden Sie in regelmäßigen Abständen sowohl technische Neuigkeiten aus unserer Partnerproduktwelt als auch nützliche Entwicklertipps.
Und jetzt kommt der obligatorische Disclaimer: Die Ausführungen der Blogeinträge spiegeln nicht die Meinung der avono AG sondern nur die Sicht der einzelnen Autoren wider.

Weitere Blogeinträge