在应用程序中,我收到了一个应用过滤器的文本,我想将此过滤结果存储到lucene Document
对象中。我不关心原文。
String stringToProcess = "...";
TokenStream stream = analyzer.tokenStream(null, new StringReader(stringToProcess));
TokenStream procStream = new CustomFilter(stream, opts);
Document luceneDocument = new Document();
FieldType ft = new FieldType(TextField.TYPE_STORED);
ft.setOmitNorms(false);
ft.setStoreTermVectors(true);
luceneDocument.add(new Field("content", procStream, ft));
这引发:
Exception in thread "main" java.lang.IllegalArgumentException: TokenStream fields cannot be stored
如果我将TextField.TYPE_STORED
更改为TYPE_NOT_STORED
则没有例外。但是,该字段的内容为null
。 Field
有一个明确接受TokenStream
对象的构造函数。
我可以使用procStream
和.incrementToken()
从.getAttribute(ChatTermAttribute.class)
手动提取令牌。
我的问题:如何将TokenStream
传递给Field对象?
答案 0 :(得分:2)
您无法传入令牌流并存储该字段。
TokenStream是经过分析的可索引标记的流。存储的字段内容是预分析字符串。您没有在字段中提供该字符串,因此它没有任何适合存储的内容,因此例外。
相反,在Analyzer
中设置IndexWriterConfig
更为常见,让它为您分析字段。我猜测你这样做的原因而不是让IndexWriter处理它是因为你想将CustomFilter
添加到开箱即用的分析器中。相反,只需创建自己的自定义Analyzer
即可。分析仪很简单。只需复制要使用的分析器的来源,然后将自定义过滤器添加到createComponents
中的链中。说你使用StandardAnalyzer,然后你改变你复制的incrementToken方法,如下所示:
@Override
protected TokenStreamComponents createComponents(final String fieldName) {
final StandardTokenizer src = new StandardTokenizer();
src.setMaxTokenLength(maxTokenLength);
TokenStream tok = new StandardFilter(src);
tok = new LowerCaseFilter(tok);
tok = new StopFilter(tok, stopwords);
tok = new CustomFilter(tok, opts); //Just adding this line
return new TokenStreamComponents(src, tok) {
@Override
protected void setReader(final Reader reader) {
src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
super.setReader(reader);
}
};
}
然后您可以创建您的字段,如:
new Field("content", stringToProcess, ft);
好的,所以我认为这有点XY problem。需要注意的是,创建自定义分析器非常可能是更好的解决方案,您实际上可以将TokenStream传递给Field并存储它,您只需提供要存储的字符串以及的TokenStream。这看起来像这样:
Field myField = new Field("content", stringToProcess, ft);
myField.setContentStream(procStream);