我正在尝试使用Apache Lucene进行标记,我对从TokenStream
获取标记的过程感到困惑。
最糟糕的是,我正在查看解决我问题的JavaDocs中的注释。
不知何故,应该使用AttributeSource
,而不是Token
。我完全不知所措。
任何人都可以解释如何从TokenStream获取类似令牌的信息吗?
答案 0 :(得分:111)
是的,这有点令人费解(与好的方式相比),但是应该这样做:
TokenStream tokenStream = analyzer.tokenStream(fieldName, reader);
OffsetAttribute offsetAttribute = tokenStream.getAttribute(OffsetAttribute.class);
TermAttribute termAttribute = tokenStream.getAttribute(TermAttribute.class);
while (tokenStream.incrementToken()) {
int startOffset = offsetAttribute.startOffset();
int endOffset = offsetAttribute.endOffset();
String term = termAttribute.term();
}
根据Donotello的说法,TermAttribute
已弃用CharTermAttribute
。根据jpountz(和Lucene的文档),addAttribute
比getAttribute
更令人满意。
TokenStream tokenStream = analyzer.tokenStream(fieldName, reader);
OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
tokenStream.reset();
while (tokenStream.incrementToken()) {
int startOffset = offsetAttribute.startOffset();
int endOffset = offsetAttribute.endOffset();
String term = charTermAttribute.toString();
}
答案 1 :(得分:36)
这是应该的样子(亚当回答的简洁版本):
TokenStream stream = analyzer.tokenStream(null, new StringReader(text));
CharTermAttribute cattr = stream.addAttribute(CharTermAttribute.class);
stream.reset();
while (stream.incrementToken()) {
System.out.println(cattr.toString());
}
stream.end();
stream.close();
答案 2 :(得分:1)
OP问题有两种变体:
Lucene documentation for Token
的最新版本说(强调添加):
注意:从2.9开始,不一定使用Token,使用新的TokenStream API,它可以用作实现所有属性的便利类,这对于轻松特别有用从旧的TokenStream API切换到新的TokenStream API。
而TokenStream
表示其API:
...已从基于令牌的转变为基于属性的...存储令牌信息的首选方法是使用AttributeImpls。
此问题的其他答案涵盖了上面的#2:如何从" new"中的TokenStream
获取类似于令牌的信息。使用属性的推荐方式。通过阅读文档,Lucene开发人员建议,这一变化部分是为了减少一次创建的单个对象的数量。
但正如有些人在这些答案的评论中指出的那样,他们并没有直接回答#1:如果你真的想要/需要这种类型,你如何获得Token
?
通过相同的API更改,TokenStream
成为AttributeSource
,Token
现在实现Attribute
,可以与TokenStream.addAttribute一起使用,就像其他答案所示适用于CharTermAttribute
和OffsetAttribute
。所以他们确实回答了原始问题的那一部分,他们根本就没有表现出来。
重要的是,虽然这种方法允许您在循环时访问Token
,但无论流中有多少逻辑令牌,它仍然只是一个对象。每次拨打incrementToken()
都会更改从Token
返回的addAttribute
的状态;因此,如果您的目标是构建一个在循环外使用的不同Token
对象的集合,那么您需要做一些额外的工作来创建新 Token
对象作为(深?)复制。
答案 3 :(得分:1)
最新版本的lucene 7.3.1
// Test the tokenizer
Analyzer testAnalyzer = new CJKAnalyzer();
String testText = "Test Tokenizer";
TokenStream ts = testAnalyzer.tokenStream("context", new StringReader(testText));
OffsetAttribute offsetAtt = ts.addAttribute(OffsetAttribute.class);
try {
ts.reset(); // Resets this stream to the beginning. (Required)
while (ts.incrementToken()) {
// Use AttributeSource.reflectAsString(boolean)
// for token stream debugging.
System.out.println("token: " + ts.reflectAsString(true));
System.out.println("token start offset: " + offsetAtt.startOffset());
System.out.println(" token end offset: " + offsetAtt.endOffset());
}
ts.end(); // Perform end-of-stream operations, e.g. set the final offset.
} finally {
ts.close(); // Release resources associated with this stream.
}
参考:https://lucene.apache.org/core/7_3_1/core/org/apache/lucene/analysis/package-summary.html