在应用程序中,我收到一个文本,在该文本上应用过滤器,并且我希望将此过滤后的结果存储到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对象? 最佳答案
您不能只传递TokenStream并存储字段。
TokenStream是经过分析的可索引令牌的流。字段的存储内容是预分析字符串。您没有将该字符串提供给字段,因此它没有任何适合存储的内容,因此是例外。
取而代之的是,在Analyzer
中设置IndexWriterConfig
并让其为您分析该字段将更为典型。我猜想您这样做而不是让IndexWriter处理的原因是因为您要将那个CustomFilter
添加到开箱即用的分析器中。相反,只需创建自己的自定义Analyzer
。分析仪很简单。只需复制要使用的分析仪的源,然后将自定义过滤器添加到createComponents
中的链中。说您使用StandardAnalyzer,然后您将更改复制的增量令牌方法,如下所示:
@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);