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

Я пытаюсь использовать 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 s. Я полностью в недоумении.

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

И TokenStream говорит о своем API:

... переместился с Token-based на основе Attribute... предпочтительным способом хранения информации Token является использование AttributeImpls.

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

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

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

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