Java | Lucene | TokenStream字段无法存储

时间:2017-11-06 09:21:19

标签: java lucene

在应用程序中,我收到了一个应用过滤器的文本,我想将此过滤结果存储到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则没有例外。但是,该字段的内容为nullField有一个明确接受TokenStream对象的构造函数。

我可以使用procStream.incrementToken().getAttribute(ChatTermAttribute.class)手动提取令牌。

我的问题:如何将TokenStream传递给Field对象?

1 个答案:

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