web-dev-qa-db-fra.com

Comment obtenir un jeton d'un Lucene TokenStream?

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.

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

D'une manière ou d'une autre, un AttributeSource est censé être utilisé, plutôt que Tokens. Je suis totalement perdu.

Quelqu'un peut-il expliquer comment obtenir des informations de type jeton à partir d'un TokenStream?

72
Eric Wilson

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

Modifier: La manière nouvelle

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

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

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

1
Flamingo

Il existe deux variantes dans la question OP:

  1. Quel est "le processus pour obtenir des jetons d'un TokenStream"?
  2. "Quelqu'un peut-il expliquer comment obtenir des informations de type jeton à partir d'un TokenStream?"

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?).

1
William Price