Как получить токен от Lucene TokenStream?


Я пытаюсь использовать Apache Lucene для токенизации, и я озадачен процессом получения токенов от A TokenStream.

худшая часть заключается в том, что я смотрю на комментарии в JavaDocs, которые касаются моего вопроса.

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

- то, что является AttributeSource предполагается использовать, а не Tokens. Я в полном недоумении.

может ли кто-нибудь объяснить, как получить токен-подобную информацию из TokenStream?

4 68

4 ответа:

Да, это немного запутанно (по сравнению с хорошим способом), но это должно сделать это:

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();
}

Edit: The новая путь

по данным 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();
}

вот как это должно быть (чистая версия ответа Адама):

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();

есть два варианта вопроса OP:

  1. что такое "процесс получения токенов из TokenStream"?
  2. может ли кто-нибудь объяснить, как получить токен-подобную информацию из TokenStream?"

последние версии Lucene документация для Token говорят (Курсив мой):

Примечание: начиная с 2.9 ... это не надо чтобы использовать токен больше, с новым TokenStream API его можно использовать как класс удобства, который реализует все атрибуты, что особенно полезно для легкого переключения со старого на новый API TokenStream.

и TokenStream говорит его API:

... перешел от использования маркеров к использованию атрибутов ... предпочтительным способом хранения информации о токене является использование AttributeImpls.

другие ответы на этот вопрос охватывают # 2 выше: как получить token-like сведениями из TokenStream в" новом " рекомендуемом способе с использованием атрибутов. Читая документацию, разработчики Lucene предполагают, что это изменение было сделано, в частности, чтобы уменьшить количество отдельных объектов, создаваемых одновременно.

но, как некоторые люди указали в комментариях к этим ответам, они прямо не отвечают #1: Как вы получаете Token Если вы действительно хотите/нужно типа?

с тем же изменением API, что делает TokenStream an AttributeSource,Token теперь реализует Attribute и может использоваться с TokenStream.addAttribute как и другие ответы показывают на CharTermAttribute и OffsetAttribute. Поэтому они действительно ответили на эту часть первоначального вопроса, они просто не показали этого.

важно, что этот подход позволит вам получить доступ к Token пока вы выполняете цикл, это все еще только один объект, независимо от того, сколько логических токенов находится в потоке. Каждый звонок к incrementToken() изменить состояние Token вернулся из addAttribute; так что если ваша цель состоит в том, чтобы построить коллекцию различных Token объекты, которые будут использоваться вне цикла, то вам потребуется сделать дополнительную работу, чтобы сделать новаяToken объект как (глубоко?) копия.

для последней версии 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