2016-07-07 55 views
0

我正在使用德語語言分析程序標記某些內容。我知道它基本上是一個「小寫」,「german_stop」,「german_keywords」,「german_normalization」,「german_stemmer」的宏過濾器。Elasticsearch如何配置語言分析器(德語)或構建自定義標準化程序

我的問題與規範化過濾器有關。這裏是過濾器的Elasticsearch DocumentationLucene Implementation。問題是ae ue和oe被視爲德文字母ä,ö和ü,因此轉換爲a,o,u。

第二次轉換是好的,但第一次轉換會導致比解決問題更多的問題。在德語文本中通常沒有ae,ue,oe表示ä,ü,ö。他們實際上出現的大部分時間都是外來詞,來自拉丁語或英語,如'Aearodynamik'(空氣動力學)。然後過濾器將'Ae'解釋爲'Ä',然後將其轉換爲'A'。這產生了'arodynamik'作爲標記。通常這不是問題,因爲搜索詞也用該過濾器標準化。然而,如果與通配符搜索結合使用,這會產生問題:

想象一個像'FooEdit'這樣的詞,它將被標記爲'foodit'。搜索'edit OR * edit *'(這是我在用戶搜索'edit'時的正常搜索),因爲'edit'的'e'丟失了,所以不會產生結果。由於我的內容有很多這樣的詞彙,而且人們正在搜索部分詞彙,所以它看起來並不像邊緣案例那麼多。

所以我的問題是有什麼辦法擺脫'ae - >'轉型?我的理解是,這是German2 snowball algorithm的一部分,所以這可能不能改變。這是否意味着我將不得不擺脫整個標準化步驟,或者我可以提供我自己的雪球算法版本,在那裏我只剝去我不喜歡的部分(沒有找到任何有關如何使用自定義的文檔用於規範化的雪球算法)?

乾杯

湯姆

回答

0

正如你所說,德國分析儀是管道結合你列出的步驟。 (Documentation

在理論上,你可以指定自己的分析就像上面,並用另一個替換german_normalization過濾器。例如一個Pattern Replace Token Filter。我從來沒有使用過,但我猜的語法等於字符替換令牌過濾器(link)。

+0

這個問題,我相信,通配符,模糊和正則表達式查詢子句不會被分析,所以'aerody *'不匹配'arodynamik「 – femtoRgon

+0

@femtoRgon我看,我沒有正確閱讀:( – Slomo

0

這種轉變是由GermanNormalizationFilter處理,而不是詞幹。這真的不是那麼困難的一類,以瞭解(不像許多詞幹),如果我理解正確的話,看起來像一個行變化會得到你想要你想要的:

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; 
    } 
    } 
} 

使用到位的german_normalization應該做的訣竅。

+0

你說得對,它是沒有太大的改變,應該如何表現在代碼中的細節問題的。不過即使我會做出改變,以算法本身,我不知道怎樣才能用它insde Elasticsearch (我最初的問題的最後一句)。 – Tom