我有一些像这样的定制分析仪:
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的正确方法感到不知所措。我不得不假设我正在使我的分析仪出错或者其他什么,但是我看不出我能以不同的方式做到这一点,它在早期版本中运行得很好。
答案 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));
}
}