【问题标题】:Lucene. index a few tokens for each word in the text卢森。为文本中的每个单词索引几个标记
【发布时间】:2015-12-27 10:17:26
【问题描述】:

我正在使用带有 SpanishAnalyzer 的 lucene 3.5(它本身使用 SpanishStemmerStandardTokenizer)。
当 SpanishAnalyzer 索引包含单词(例如)“claramente”和“claro”的文档时,它们都将被索引为“clar”。
这种行为被理解并且对我的需求很有用,今天在查询之前,我使用分析器的tokenStream + incrementToken() 来获取我的搜索词的标记并针对索引文档进行搜索。我没有使用 QueryParser,而是在代码中构建 lucene 查询对象。
但是,我希望能够搜索确切的单词(在此示例中为 claro),而不会失去 SpanishAnalyzer 的形态学能力。
我可以跳过上面的步骤(tokenStream)并直接搜索“claro”,但它不会被找到,因为它被索引为“clar”。
此外,我不想使用 2 个不同的分析器对该字段进行两次索引,因为我需要能够使用包含一个精确单词和一个常规术语(形态学)的 PhraseQuerySpanNearQuery
所以……我要说到点子上了……我想修改 Tokenizer 或 Stemmer 或 Filter (?) 所以在索引时间它将为每个单词索引 2 个标记,词干一个和原始一个,在这种情况下“claro " 和 "clar" 以及以后查询时,我可以选择是使用确切的单词还是词干标记。
我需要帮助了解如何(以及在​​哪里)我可以做到这一点,我想编辑应该在 Stemmer 的某个地方完成。

顺便说一句,我在使用 incrementToken() 时为文本中的每个单词返回多个标记的希伯来语分析器完全相同(但我没有源代码)

【问题讨论】:

    标签: java lucene query-analyzer


    【解决方案1】:

    您需要一个每个位置包含多个标记的索引,因为您希望搜索包含词干标记和非词干(=原始)标记的短语。 我会回答 5.3 版,但 3.5 版差别不大。

    看一下solr中ReversedWildcardFilter的源代码。 您将在每个令牌上看到两个步骤:

    1. 用原始令牌存储当前state。所以incrementToken()-方法的第一次调用会得到词干标记,第二次调用会得到原始标记(位置相同)
    2. 选择“markerChar”作为词干标记的前缀。因此,在搜索时,您可以决定是使用词干标记还是原始标记进行搜索。

    对于您的 SpanishAnalyzer,这意味着例如以下:

    SpanishAnalyzer 的核心是 SpanishLightStemFilter。 SpanishLightStemFilter 仅使用 !KeywordAttribute.isKeyword() 提取 Token。因此,对于索引时间,在 SpanishAnalyzer 中插入一个 KeywordRepeatFilter 并用前缀标记词干标记。

    【讨论】:

    • 谢谢,这很有帮助!我不太明白你的最后一句话......而且我的SpanishAnalyzer 使用SpanishStemmer 而不是SpanishLightStemFilter(猜想它们是相似的)但我所做的是从ReversedWildcardFilter 中获取相关的代码行并添加他们给我的SnowballFilter.incrementToken(),实际上我现在每个词得到 2 个标记(词干和原始)
    【解决方案2】:

    有一个标记过滤器可以很容易地实现这一点,KeywordRepeatFilterSpanishLightStemFilter 确实尊重 KeywordAttribute)。只需将其添加到您的分析链中,就在 Stemmer 之前。对于 SpanishAnalyzer,createComponents 方法如下所示:

    @Override
    protected TokenStreamComponents createComponents(String fieldName) {
        final Tokenizer source;
        if (getVersion().onOrAfter(Version.LUCENE_4_7_0)) {
            source = new StandardTokenizer();
        } else {
            source = new StandardTokenizer40();
        }
        TokenStream result = new StandardFilter(source);
        result = new LowerCaseFilter(result);
        result = new StopFilter(result, stopwords);
        if(!stemExclusionSet.isEmpty())
            result = new SetKeywordMarkerFilter(result, stemExclusionSet);
        result = new KeywordRepeatFilter(result);
        result = new SpanishLightStemFilter(result);
        return new TokenStreamComponents(source, result);
    }
    

    这将不允许您显式搜索仅无词干的词,但它会将原始词保持在与词干相同的位置,从而可以轻松地将它们分解为短语查询。如果您确实需要仅显式搜索词干或非词干术语,那么在单独的字段中建立索引确实是更好的方法。

    【讨论】:

      猜你喜欢
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      • 1970-01-01
      • 2012-06-27
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多