2016-07-07 29 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