我目前正在将搜索引擎应用程序从Lucene 3.5.0升级到版本4.10.3。版本4中有一些实质性的API更改会破坏向后兼容性。我已经设法解决了大部分问题,但仍然存在一些问题,我可以使用一些帮助:
原始代码扩展了Analyzer类和overrode tokenStream(...)。
@Override
public TokenStream tokenStream(String fieldName, Reader reader) {
CharStream charStream = CharReader.get(reader);
return
new LowerCaseFilter(version,
new SeparationFilter(version,
new WhitespaceTokenizer(version,
new HTMLStripFilter(charStream))));
}
但是这种方法现在是最终的,我不知道如何理解更改日志中的以下注释:
ReusableAnalyzerBase已重命名为Analyzer。所有Analyzer实现现在必须使用Analyzer.TokenStreamComponents,而不是重写.tokenStream()和.reusableTokenStream()(现在是最终的)。
上面引用的方法还有另一个问题:
这里似乎也有一些相当大的变化。
这个课现在已经在Lucene 4中消失了。对此有什么简单的修正吗?从更改日志中:
术语向量API(TermFreqVector,TermPositionVector,TermVectorMapper)已被删除,有利于上述灵活的索引API,从术语向量呈现文档的单文档倒排索引。
可能与此相关:
这两个问题都出现在这里,例如:
TermPositionVector termVector = (TermPositionVector) reader.getTermFreqVector(...);
("读者"属于IndexReader类型)
我很感激对这些问题的任何帮助。
答案 0 :(得分:1)
我在Lucene邮件列表中找到了核心开发人员Uwe Schindler的response。我花了一些时间来绕过新的API,所以我需要在忘记之前写下来。
这些说明适用于Lucene 4.10.3。
new Analyzer() {
@Override
protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
Tokenizer source = new WhitespaceTokenizer(new HTMLStripCharFilter(reader));
TokenStream sink = new LowerCaseFilter(source);
return new TokenStreamComponents(source, sink);
}
};
Analyzer.tokenStream()
返回的令牌流的最终结果,因此将其设置为过滤器链。在应用任何过滤器之前,源是令牌流。术语向量在Lucene 4中的工作方式不同,因此没有直接的方法交换。具体答案取决于您的要求。
如果您需要位置信息,则必须首先使用位置信息索引字段:
Document doc = new Document();
FieldType f = new FieldType();
f.setIndexed(true);
f.setStoreTermVectors(true);
f.setStoreTermVectorPositions(true);
doc.add(new Field("text", "hello", f));
最后,为了获得文档字段的频率和位置信息,您可以深入了解这样的新API(改编自this answer):
// IndexReader ir;
// int docID = 0;
Terms terms = ir.getTermVector(docID, "text");
terms.hasPositions(); // should be true if you set the field to store positions
TermsEnum termsEnum = terms.iterator(null);
BytesRef term = null;
// Explore the terms for this field
while ((term = termsEnum.next()) != null) {
// Enumerate through documents, in this case only one
DocsAndPositionsEnum docsEnum = termsEnum.docsAndPositions(null, null);
int docIdEnum;
while ((docIdEnum = docsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
for (int i = 0; i < docsEnum.freq(); i++) {
System.out.println(term.utf8ToString() + " " + docIdEnum + " "
+ docsEnum.nextPosition());
}
}
}
如果Terms.iterator()
返回实际的Iterable,那就太好了。