我正在尝试将CharFilter添加到我的StandardAnalyzer中。我的意图是从我索引的所有文本中删除标点符号;例如,我希望PrefixQuery“pf”匹配“P.F. Chang's”或“zaras”以匹配“Zara's”。

看来,最简单的攻击方法是在分析之前过滤掉所有标点符号。对于Analyzer package documentation,这意味着我应该使用CharFilter

但是,将CharFilter实际插入分析器似乎几乎是不可能的!

Analyzer.initReader的JavaDoc说“如果要插入CharFilter,请覆盖此内容”。

如果我的代码扩展了Analyzer,则可以扩展initReader,但不能将抽象createComponents委派给我的基础StandardAnalyzer,因为它受到保护。我无法将tokenStream委托给我的基本分析器,因为它是最终的。因此,分析器的子类似乎无法使用其他分析器来完成其肮脏的工作。

有一个AnalyzerWrapper类对于我想要的东西似乎很完美!我可以提供基本分析器,并且仅覆盖我想要的部分。除了…initReader已经被覆盖以委托给基本分析器,并且此覆盖是“最终的”! mm!

我想我可以将Analyzer放在org.apache.lucene.analyzers包中,然后可以访问受保护的createComponents方法,但这似乎是一种令人厌恶的hacky方式,它绕过了我本应使用的公共API。

我想念这里刺眼的东西吗?如何修改StandardAnalyzer以使用自定义CharFilter

最佳答案

目的是让您覆盖Analyzer而不是StandardAnalyzer。这种想法是,您永远不应将分析器实现子类化(有关here的一些讨论)。但Analyzer的实现非常简单,将一个CharFilter添加到Analyzer中,实现与StandardAnalyzer相同的标记器/过滤器链,如下所示:

public final class MyAnalyzer {
    @Override
    protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
        final StandardTokenizer src = new StandardTokenizer(matchVersion, reader);
        TokenStream tok = new StandardFilter(matchVersion, src);
        tok = new LowerCaseFilter(matchVersion, tok);
        tok = new StopFilter(matchVersion, tok, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
        return new TokenStreamComponents(src, tok);
    }

    @Override
    protected Reader initReader(String fieldName, Reader reader) {
        //return your CharFilter-wrapped reader here
    }
}

09-16 12:09