【问题标题】:TokenStream contract violation when using custom Analyzer with Lucene 4.9将自定义分析器与 Lucene 4.9 一起使用时违反 TokenStream 合同
【发布时间】:2014-07-18 19:06:18
【问题描述】:

我有几个像这样的自定义分析器:

private static class ModelAnalyzer extends Analyzer
{
    @Override
    protected TokenStreamComponents createComponents(String string, Reader reader)
    {
        return new TokenStreamComponents(
            new StandardTokenizer(Version.LUCENE_4_9, reader),
            new LowerCaseFilter(Version.LUCENE_4_9,
                new NGramTokenFilter(Version.LUCENE_4_9,
                    new CharTokenizer(Version.LUCENE_4_9, reader)
                    {
                        @Override
                        protected boolean isTokenChar(int c)
                        {
                            return Character.isLetterOrDigit(c);
                        }
                    }, 3, 20)));
    }
}

它们被添加到 PerFieldAnalyzerWrapper 并添加到我的 IndexWriterConfig。当我尝试重建索引时,将第二个文档添加到索引时总是出现错误:

java.lang.IllegalStateException: TokenStream contract violation: reset()/close() call missing, reset() called multiple times, or subclass does not call super.reset(). Please see Javadocs of TokenStream class for more information about the correct consuming workflow.

我所做的只是将文档添加到我的 IndexWriter。我没有以任何方式接触这些过滤器或标记器,因此我没有干净的方法可以在它们上调用 reset()。没有我的帮助,IndexWriter 不应该遵循“正确的消费工作流程”吗?

在网上阅读了 8 小时后,我放弃了,只是将 Version.LUCENE_4_5 传递给我的每个标记器和过滤器,以便不运行烦人的状态机检查(我理解是在 4_6 中添加的)。这已经解决了这个问题,但我不知道使用 4.9 进行这项工作的正确方法。我不得不假设我的分析器出错了或其他什么,但我看不出我可以如何做不同的事情,而且它在早期版本中工作得很好。

【问题讨论】:

    标签: lucene analyzer


    【解决方案1】:

    也许问题在于您添加了两次阅读器。以这种方式它必须工作:

    Tokenizer tokenizer = new StandardTokenizer(Version.LUCENE_4_9, reader);
    TokenFilter filters = new LowerCaseFilter(Version.LUCENE_4_9, tokenizer);
    filters = new NGramTokenFilter(Version.LUCENE_4_9, filters);
    filters = ...
    return new TokenStreamComponents(tokenizer, filters);
    

    【讨论】:

    • 感谢您帮助我找到解决方案。您确实标记了问题,但您的代码可能不是解决问题的正确方法。在对如何正确记录这个解决方案犹豫不决之后,我决定我应该发布确切的答案,以便其他人更容易一眼看出我认为更正确的解决方案。
    【解决方案2】:

    Javi 指出我的阅读器可能被使用了两次,从而为我指明了正确的方向。我回到我的分析仪并利用当前预写的组件从头开始重写它。这现在完美无缺。基本上关键是保持简单,不要尝试直接移植。

    private static class ModelAnalyzer extends Analyzer
    {
        @Override
        protected TokenStreamComponents createComponents(String string, Reader reader)
        {
            Tokenizer tokenizer = new NGramTokenizer(Version.LUCENE_4_9, reader, 3, 20)
            {
                @Override
                protected boolean isTokenChar(int c)
                {
                    return Character.isLetterOrDigit(c);
                }
            };
            return new TokenStreamComponents(tokenizer,
                new LowerCaseFilter(Version.LUCENE_4_9, tokenizer));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多