java - ¿Cómo obtener un TokenStream de un Lucene TokenStream?
attributes tokenize (4)
Intento usar Apache Lucene para tokenizar, y estoy desconcertado en el proceso para obtener Tokens de un TokenStream
.
La peor parte es que estoy viendo los comentarios en los JavaDocs que abordan mi pregunta.
De alguna manera, se supone que se debe usar un AttributeSource
, en lugar de Token
s. Estoy totalmente perdido.
¿Alguien puede explicar cómo obtener información similar a un token de un TokenStream?
Así es como debe ser (una versión limpia de la respuesta de Adán):
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();
Hay dos variaciones en la pregunta OP:
- ¿Cuál es "el proceso para obtener Tokens de un TokenStream"?
- "¿Alguien puede explicar cómo obtener información similar a un token de un TokenStream?"
Las versiones recientes de la documentación de Lucene para Token
dicen (énfasis añadido):
NOTA: A partir de 2.9 ... ya no es necesario usar TokenStream, con la nueva API TokenStream se puede utilizar como clase de conveniencia que implementa todos los Atributos, lo que es especialmente útil para cambiar fácilmente de la antigua a la nueva API de TokenStream.
Y TokenStream
dice que su API:
... ha pasado de estar basado en tokens a basado en atributos ... la forma preferida de almacenar la información de un token es usar AttributeImpls.
Las otras respuestas a esta pregunta cubren el número 2 anterior: cómo obtener información similar a un TokenStream
un TokenStream
en la "nueva" forma recomendada mediante el uso de atributos. Al leer la documentación, los desarrolladores de Lucene sugieren que este cambio se realizó, en parte, para reducir el número de objetos individuales creados a la vez.
Pero como algunas personas han señalado en los comentarios de esas respuestas, no responden directamente al # 1: ¿cómo obtienes un Token
si realmente quieres / necesitas ese tipo?
Con el mismo cambio de API que hace que TokenStream
sea un AttributeSource
, Token
ahora implementa Attribute
y se puede usar con TokenStream.addAttribute al igual que las otras respuestas muestran para CharTermAttribute
y OffsetAttribute
. Entonces respondieron realmente esa parte de la pregunta original, simplemente no la mostraron.
Es importante que, si bien este enfoque le permitirá acceder a Token
mientras realiza un bucle, siga siendo solo un objeto, sin importar cuántos tokens lógicos haya en la transmisión. Cada llamada a incrementToken()
cambiará el estado del Token
devuelto desde addAttribute
; Entonces, si su objetivo es construir una colección de diferentes objetos Token
para usar fuera del ciclo, entonces deberá hacer un trabajo adicional para crear un nuevo objeto Token
como una copia (¿profunda?).
Para la última versión de 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.
}
Referencia: https://lucene.apache.org/core/7_3_1/core/org/apache/lucene/analysis/package-summary.html
Sí, es un poco intrincado (comparado con el buen estilo), pero debería hacerlo:
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();
}
Editar: La nueva forma
Según Donotello, TermAttribute
ha quedado en desuso en favor de CharTermAttribute
. Según jpountz (y la documentación de Lucene), addAttribute
es más deseable que 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();
}