Lucene的连字符

时间:2010-04-08 14:56:19

标签: lucene lucene.net

我正在玩Lucene,并注意到使用连字符(例如“半决赛”)将导致两个单词(索引中的“半”和“最终”。如果匹配的话,这应该如何匹配用户用一个词来搜索“半决赛”吗?

编辑:我实际上只是在玩StandardTokenizer类,也许这就是为什么?我错过了过滤器吗?

谢谢!

(编辑) 我的代码如下所示:

            StandardAnalyzer sa = new StandardAnalyzer();
            TokenStream ts = sa.TokenStream("field", new StringReader("semi-final"));

            while (ts.IncrementToken())
            {
                string t = ts.ToString();
                Console.WriteLine("Token: " + t);
            }

5 个答案:

答案 0 :(得分:2)

我建议你使用Solr的WordDelimiterFilter(你可以在你的Lucene应用程序中使用它作为添加到你的分析器的TokenFilter,只需从Solr获取此过滤器的java文件并将其添加到你的应用程序中)。 / p>

此过滤器旨在处理如下情况: http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters#solr.WordDelimiterFilterFactory

答案 1 :(得分:1)

这是lucene中的tokenizer的解释

- Splits words at punctuation
   characters, removing punctuation.
   However, a dot that's not followed by
   whitespace is considered part of a
   token. 

 - Splits words at hyphens, unless
   there's a number in the token, in
   which case the whole token is
   interpreted as a product number and
   is not split.

 - Recognizes email addresses and internet hostnames as one token.

Found here

这解释了为什么它会分裂你的话。

这可能是最难纠正的,人为错误。如果一个人在半决赛中输入,这在理论上与搜索半决赛不同。所以如果你有很多单词可以用不同的方式输入ex:

  

的St-恒

     

圣常数

     

圣恒

你坚持完成任务 st和saint以及连字符或非连字符。你的代币将是巨大的,每个单词都需要进行比较,看看它们是否匹配。

我仍然在寻找是否有一种很好的方法来接近这个,否则,如果你没有很多想要使用的单词,那么就可以存储和测试所有的可能性,或者有一个循环分裂从第一个字母开始的单词并在每个字母中移动,将字符串分成两半以形成两个单词,测试整个过程以查看它是否匹配。但再次说你只有2个字。如果您要验证多于两个单词,那么您就会遇到在多个部分中拆分单词的问题

例如

  

saint-jean-sur-richelieu

如果我拿出别的东西,我会告诉你。

答案 2 :(得分:1)

如果您正在寻找WordDelimiterFilter的端口,那么我建议谷歌WordDelimiter.cs,我在这里找到了这样一个端口:

http://osdir.com/ml/attachments/txt9jqypXvbSE.txt

然后我创建了一个非常基本的WordDelimiterAnalyzer:

public class WordDelimiterAnalyzer: Analyzer
{
    #region Overrides of Analyzer

    public override TokenStream TokenStream(string fieldName, TextReader reader)
    {
        TokenStream result = new WhitespaceTokenizer(reader);

        result = new StandardFilter(result);
        result = new LowerCaseFilter(result);
        result = new StopFilter(true, result, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
        result = new WordDelimiterFilter(result, 1, 1, 1, 1, 0);

        return result;
    }

    #endregion
}

我说这是基本的:)

如果有人有实施,我会很想看到它!

答案 3 :(得分:0)

您可以编写自己的标记生成器,它将为带有连字符的单词生成所有可能的标记组合:

  • 半决赛
  • 最终

您需要设置正确的令牌偏移量来告诉lucene半场半决赛实际上是从文档中的同一位置开始的。

答案 4 :(得分:0)

规则(对于经典分析器)来自于jflex:

// floating point, serial, model numbers, ip addresses, etc.
// every other segment must have at least one digit
NUM        = ({ALPHANUM} {P} {HAS_DIGIT}
           | {HAS_DIGIT} {P} {ALPHANUM}
           | {ALPHANUM} ({P} {HAS_DIGIT} {P} {ALPHANUM})+
           | {HAS_DIGIT} ({P} {ALPHANUM} {P} {HAS_DIGIT})+
           | {ALPHANUM} {P} {HAS_DIGIT} ({P} {ALPHANUM} {P} {HAS_DIGIT})+
           | {HAS_DIGIT} {P} {ALPHANUM} ({P} {HAS_DIGIT} {P} {ALPHANUM})+)

// punctuation
P            = ("_"|"-"|"/"|"."|",")