如何从Lucene TokenStream获取令牌?

时间:2010-04-14 14:30:35

标签: java attributes lucene token tokenize

我正在尝试使用Apache Lucene进行标记,我对从TokenStream获取标记的过程感到困惑。

最糟糕的是,我正在查看解决我问题的JavaDocs中的注释。

http://lucene.apache.org/java/3_0_1/api/core/org/apache/lucene/analysis/TokenStream.html#incrementToken%28%29

不知何故,应该使用AttributeSource,而不是Token。我完全不知所措。

任何人都可以解释如何从TokenStream获取类似令牌的信息吗?

4 个答案:

答案 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的文档),addAttributegetAttribute更令人满意。

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问题有两种变体:

  1. 什么是"从TokenStream获取令牌的过程"?
  2. "任何人都可以解释如何从TokenStream获取类似令牌的信息吗?"
  3. Lucene documentation for Token的最新版本说(强调添加):

      

    注意:从2.9开始,不一定使用Token,使用新的TokenStream API,它可以用作实现所有属性的便利类,这对于轻松特别有用从旧的TokenStream API切换到新的TokenStream API。

    TokenStream表示其API:

      

    ...已从基于令牌的转变为基于属性的...存储令牌信息的首选方法是使用AttributeImpls。

    此问题的其他答案涵盖了上面的#2:如何从" new"中的TokenStream获取类似于令牌的信息。使用属性的推荐方式。通过阅读文档,Lucene开发人员建议,这一变化部分是为了减少一次创建的单个对象的数量。

    但正如有些人在这些答案的评论中指出的那样,他们并没有直接回答#1:如果你真的想要/需要这种类型,你如何获得Token

    通过相同的API更改,TokenStream成为AttributeSourceToken现在实现Attribute,可以与TokenStream.addAttribute一起使用,就像其他答案所示适用于CharTermAttributeOffsetAttribute。所以他们确实回答了原始问题的那一部分,他们根本就没有表现出来。

    重要的是,虽然这种方法允许您在循环时访问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