我正在尝试使用Apache Lucene进行令牌化,但我对从中获取令牌的过程感到困惑TokenStream
。
最糟糕的部分是我正在查看JavaDocs中解决我的问题的注释。
不知何故,AttributeSource
应该使用an而不是Token
s。我完全不知所措。
谁能解释如何从TokenStream获得类似令牌的信息?
我正在尝试使用Apache Lucene进行令牌化,但我对从中获取令牌的过程感到困惑TokenStream
。
最糟糕的部分是我正在查看JavaDocs中解决我的问题的注释。
不知何故,AttributeSource
应该使用an而不是Token
s。我完全不知所措。
谁能解释如何从TokenStream获得类似令牌的信息?
Answers:
是的,这有点令人费解(与好的方式相比),但是应该这样做:
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();
}
reset()
给Lucene 4.3,所以
这应该是这样(Adam答案的干净版本):
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();
reset()
Lucene 4.3,所以我自由地添加了它
对于最新版本的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
OP问题有两种变体:
说说Lucene文档的Token
最新版本(添加了重点):
注意:从2.9版本开始...不再需要使用Token,对于新的TokenStream API,它可以用作实现所有属性的便捷类,这对于轻松地从旧的TokenStream API切换到新的TokenStream API特别有用。
并TokenStream
说它的API:
...已经从基于令牌的转变为基于属性的...存储令牌信息的首选方法是使用AttributeImpls。
此问题的其他答案包括上面的#2:如何使用属性以“新”推荐的方式从中获取类似令牌的信息TokenStream
。通过阅读文档,Lucene开发人员建议进行此更改,部分是为了减少一次创建的单个对象的数量。
但是,正如某些人在这些答案的注释中指出的那样,他们没有直接回答#1:Token
如果您确实想要/需要该类型,您将如何获得?
在相同的API的变化,使TokenStream
一个AttributeSource
,Token
现在实现Attribute
并可以搭配TokenStream.addAttribute就像其他的答案显示CharTermAttribute
和OffsetAttribute
。因此,他们确实回答了原始问题的那一部分,只是没有显示出来。
重要的是,尽管这种方法将允许您Token
在循环时进行访问,但是无论流中有多少逻辑标记,它仍然只是一个对象。每次致电incrementToken()
都会改变Token
返回状态addAttribute
;因此,如果您的目标是构建Token
要在循环外使用的不同对象的集合,那么您将需要做额外的工作来制作一个新的 Token
对象(深层副本)。
CharTermAttributeImpl.toString()
替代