Как получить токен из Lucene TokenStream? - PullRequest
72 голосов
/ 14 апреля 2010

Я пытаюсь использовать 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 ]

112 голосов
/ 14 апреля 2010

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

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

Редактировать: новый способ

Согласно Донотелло, 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();
}
36 голосов
/ 23 сентября 2012

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

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();
1 голос
/ 10 июня 2018

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

1 голос
/ 18 апреля 2014

В ОП вопросе есть два варианта:

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

Последние версии документации Lucene для Token скажем (выделение добавлено):

ПРИМЕЧАНИЕ. Начиная с версии 2.9 ... больше не требуется , чтобы больше использовать Token, с новым API TokenStream его можно использовать как вспомогательный класс, который реализует все атрибуты, что особенно полезно для простого переключения от старого к новому API TokenStream.

И TokenStream говорит, что его API:

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

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

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

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

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

...