与Lucene 4.9一起使用自定义分析器时,TokenStream合同违规

时间:2014-07-18 19:06:18

标签: lucene analyzer

我有一些像这样的定制分析仪:

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传递给我的每个tokenizer和过滤器,以便激活状态机检查(我理解是在4_6中添加)。这已经解决了这个问题,但是我对使用4.9的正确方法感到不知所措。我不得不假设我正在使我的分析仪出错或者其他什么,但是我看不出我能以不同的方式做到这一点,它在早期版本中运行得很好。

2 个答案:

答案 0 :(得分:2)

也许问题是你要两次添加阅读器。通过这种方式它必须工作:

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);

答案 1 :(得分:0)

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));
    }
}