Java 卢森。为文本中的每个单词索引一些标记

Java 卢森。为文本中的每个单词索引一些标记,java,lucene,query-analyzer,Java,Lucene,Query Analyzer,我正在使用lucene 3.5(它本身使用和)。 当SpanishAnalyzer用单词(例如“claramente”和“claro”)索引文档时,它们都将被索引为“clar”。 这种行为对我的需求是理解和有用的,今天在查询之前,我使用分析器的tokenStream+incrementToken()来获取搜索词的标记,并根据索引文档进行搜索。我不是在使用QueryParser,而是在代码中构建lucene查询对象。 但是,我希望能够在不丢失SpanishAnalyzer的形态学功能的情况下搜索准

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


顺便说一句,我对希伯来文分析器也做了同样的事情,它在使用
incrementToken()
(但我没有源代码)

时为文本中的每个单词返回几个标记您需要一个每个位置都有多个标记的索引,因为您希望搜索包含词干标记和非词干(=原始)标记的短语。 我将回答版本5.3,但3.5并没有太大的不同

请查看in-solr的源代码。 您将在每个令牌上看到两个步骤:

  • 将当前标记与原始标记一起存储。因此,-method的第一个调用到达带词干的令牌,第二个调用到达原始令牌(位置相同)
  • 选择“markerChar”作为词干标记的前缀。所以在搜索时,您可以决定是使用词干标记还是原始标记进行搜索
  • 对于您的SpanishAnalyzer,这意味着,例如:


    SpanishAnalyzer的核心是SpanishLightStemFilter。SpanishLightStemFilter仅使用标记作为词干。因此,对于索引时间,在SpanishAnalyzer中插入一个关键字RepeatFilter,并用前缀标记词干标记。

    有一个标记过滤器可以很容易地实现这一点,(
    SpanishLightStemFilter
    确实尊重关键字属性)。只需在词干分析器之前将其添加到分析链中。对于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);
    }
    

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

    谢谢,这非常有用!我不太明白你的最后一句话……而且我的
    SpanishAnalyzer
    使用
    SpanishStemmer
    ,而不是
    SpanishLightStemFilter
    (估计它们很相似),但我所做的是从
    ReversedWildcardFilter
    中提取相关的代码行,并将它们添加到我的
    SnowballFilter.incrementToken()
    事实上,我现在每个单词有2个标记(词干和原始)