J'essaie d'utiliser Apache Lucene pour la tokenisation, et je suis déconcerté par le processus pour obtenir des jetons à partir d'un TokenStream
.
Le pire, c'est que je regarde les commentaires dans les JavaDocs qui répondent à ma question.
D'une manière ou d'une autre, un AttributeSource
est censé être utilisé, plutôt que Token
s. Je suis totalement perdu.
Quelqu'un peut-il expliquer comment obtenir des informations de type jeton à partir d'un TokenStream?
Oui, c'est un peu compliqué (par rapport à la bonne vieille façon), mais cela devrait le faire:
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();
}
Selon Donotello, TermAttribute
a été déconseillé au profit de CharTermAttribute
. Selon jpountz (et la documentation de Lucene), addAttribute
est plus souhaitable 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();
}
Voici comment cela devrait être (une version épurée de la réponse d'Adam):
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();
Pour la dernière version 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.
}
Référence: https://lucene.Apache.org/core/7_3_1/core/org/Apache/lucene/analysis/package-summary.html
Il existe deux variantes dans la question OP:
Versions récentes de la documentation Lucene pour Token
say (soulignement ajouté):
REMARQUE: à partir de 2.9 ... il n'est plus nécessaire d'utiliser Token, avec la nouvelle API TokenStream, il peut être utilisé comme classe de commodité qui implémente tous Attributs, ce qui est particulièrement utile pour passer facilement de l'ancienne à la nouvelle API TokenStream.
Et TokenStream
dit son API:
... est passé de Token-based à Attribute-based ... la meilleure façon de stocker les informations d'un Token est d'utiliser AttributeImpls.
Les autres réponses à cette question couvrent le point 2 ci-dessus: comment obtenir des informations comme des jetons à partir d'un TokenStream
de la "nouvelle" manière recommandée en utilisant des attributs. En lisant la documentation, les développeurs de Lucene suggèrent que cette modification a été apportée, en partie, pour réduire le nombre d'objets individuels créés à la fois.
Mais comme certaines personnes l'ont souligné dans les commentaires de ces réponses, elles ne répondent pas directement # 1: comment obtenir un Token
si vous voulez/avez vraiment besoin de ce type?
Avec le même changement d'API qui fait de TokenStream
un AttributeSource
, Token
implémente désormais Attribute
et peut être utilisé avec TokenStream.addAttribute tout comme les autres réponses montrent pour CharTermAttribute
et OffsetAttribute
. Ils ont donc vraiment répondu à cette partie de la question d'origine, ils ne l'ont tout simplement pas montrée.
Il est important que cette approche vous permette d'accéder à Token
pendant que vous bouclez, mais ce n'est toujours qu'un seul objet, quel que soit le nombre de jetons logiques dans le flux. Chaque appel à incrementToken()
changera l'état du Token
retourné par addAttribute
; Donc, si votre objectif est de créer une collection d'objets Token
différents à utiliser en dehors de la boucle, vous devrez faire un travail supplémentaire pour créer un nouveau Token
objet en tant que copie (profonde?).