2016-07-07 5 views
0

Ich benutze den deutschen Sprachanalysator, um einige Inhalte zu tokenisieren. Ich weiß, dass es im Grunde ein Makrofilter für "Kleinbuchstaben", "German_Stop", "German_Keywords", "German_Normalization", "German_Stemmer" ist.Elasticsearch Wie konfiguriere ich Sprachanalysator (Deutsch) oder baue einen benutzerdefinierten Normalizer?

Mein Problem hat mit dem Nomalisierungsfilter zu tun. Hier ist der Elasticsearch Documentation und der Lucene Implementation des Filters. Das Problem ist, dass ae ue und oe wie die deutschen Buchstaben ä, ö und ü behandelt und daher in a, o, u umgewandelt werden.

Die zweite Transformation ist gut, aber die erste führt zu mehr Problemen, als sie löst. Es gibt normalerweise keine ae, ue, oe in deutschen Texten, die wirklich ä, ü, ö darstellen. Die meiste Zeit, die sie tatsächlich erscheinen, sind in ausländischen Wörtern, abgeleitet von Latein oder Englisch wie 'Aeodynamik' (Aerodynamik). Der Filter interpretiert dann "Ae" als "Ä" und wandelt ihn dann in "A" um. Dies ergibt 'Arodynamik' als Token. Normalerweise ist dies kein Problem, da das Suchwort auch mit diesem Filter normalisiert wird. Dies wird jedoch zu einem Problem, wenn es mit der Platzhaltersuche kombiniert wird:

Stellen Sie sich ein Wort wie 'FooEdit' vor, das wird zu 'foodit' tokenisiert. Eine Suche nach 'edit OR * edit *' (was meine normale Suche ist, wenn der Benutzer nach 'edit' sucht) wird kein Ergebnis ergeben, da das 'e' von 'edit' verloren gegangen ist. Da meine Inhalte so viele Wörter haben und die Leute nach Teilwörtern suchen, ist es nicht so sehr ein Randfall, wie es scheint.

Also meine Frage ist, gibt es eine Möglichkeit, die 'ae -> a' Transformationen loszuwerden? Mein Verständnis ist, dass dies Teil der German2 snowball algorithm ist, so dass dies wahrscheinlich nicht geändert werden kann. Bedeutet das, dass ich den ganzen Normalisierungsschritt loswerden muss oder kann ich meine eigene Version des Schneeballalgorithmus zur Verfügung stellen, wo ich nur die Teile abstreife, die ich nicht mag (habe keine Dokumentation gefunden, wie man einen Brauch benutzt) Schneeball-Algorithmus zur Normalisierung)?

Prost

Tom

Antwort

0

Wie Sie gesagt haben, ist der Deutsch-Analysator eine Pipeline die Schritte Kombinieren Sie aufgelistet. (Documentation)

In der Theorie könnten Sie Ihren eigenen Analysator genau wie oben spezifizieren und den german_normationization Filter durch einen anderen ersetzen. Zum Beispiel eine Pattern Replace Token Filter. Ich habe es nie benutzt, aber ich würde vermuten, dass die Syntax dem Char Replace Token Filter (link) entspricht.

+0

Das Problem, glaube ich, ist, dass Wildcard, Fuzzy und Regex Abfrage Klauseln nicht analysiert werden, so 'Aerody *' passt nicht "Arodynamik" – femtoRgon

+0

@ FemtoRgon Ich sehe, ich habe nicht richtig gelesen :( – Slomo

0

Diese Transformation wird von der GermanNormalizationFilter statt der Stemmer behandelt. Es ist wirklich nicht, dass eine Klasse schwierig (im Gegensatz zu vielen Abbeermaschinen) zu verstehen, und wenn ich richtig verstehe, sieht aus wie eine Änderung einzeiligen erhalten Sie wollen Sie wollen:

public final class CustomGermanNormalizationFilter extends TokenFilter { 
    // FSM with 3 states: 
    private static final int N = 0; /* ordinary state */ 
    private static final int V = 1; /* stops 'u' from entering umlaut state */ 
    private static final int U = 2; /* umlaut state, allows e-deletion */ 

    private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class); 

    public CustomGermanNormalizationFilter(TokenStream input) { 
    super(input); 
    } 

    @Override 
    public boolean incrementToken() throws IOException { 
    if (input.incrementToken()) { 
     int state = N; 
     char buffer[] = termAtt.buffer(); 
     int length = termAtt.length(); 
     for (int i = 0; i < length; i++) { 
     final char c = buffer[i]; 
     switch(c) { 
//Removing this case should prevent e-deletion for "ae" 
//  case 'a': 
      case 'o': 
      state = U; 
      break; 
      case 'u': 
      state = (state == N) ? U : V; 
      break; 
      case 'e': 
      if (state == U) 
       length = StemmerUtil.delete(buffer, i--, length); 
      state = V; 
      break; 
      case 'i': 
      case 'q': 
      case 'y': 
      state = V; 
      break; 
      case 'ä': 
      buffer[i] = 'a'; 
      state = V; 
      break; 
      case 'ö': 
      buffer[i] = 'o'; 
      state = V; 
      break; 
      case 'ü': 
      buffer[i] = 'u'; 
      state = V; 
      break; 
      case 'ß': 
      buffer[i++] = 's'; 
      buffer = termAtt.resizeBuffer(1+length); 
      if (i < length) 
       System.arraycopy(buffer, i, buffer, i+1, (length-i)); 
      buffer[i] = 's'; 
      length++; 
      state = N; 
      break; 
      default: 
      state = N; 
     } 
     } 
     termAtt.setLength(length); 
     return true; 
    } else { 
     return false; 
    } 
    } 
} 

Mit dass anstelle von german_normalization tun sollten der Trick.

+0

Sie haben Recht, es ist kein großes Problem, die Details zu ändern, wie es sich im Code verhalten soll, aber selbst wenn ich die Änderungen am Algorithmus selbst vornehmen würde, sehe ich nicht, wie ich es in Elasticsearch verwenden kann (letzter Satz meiner ersten Frage). – Tom

Verwandte Themen