Question Ajout de jetons à un jeton lucene


J'ai écrit un TokenFilter ce qui ajoute des jetons dans un flux.

1. Les tests montrent que cela fonctionne, mais je ne comprends pas complètement pourquoi.

Si quelqu'un pouvait faire la lumière sur la sémantique, je vous en serais reconnaissant. En particulier, à (*), restaurer l'état, cela ne signifie-t-il pas que nous écrasons le jeton actuel ou le jeton créé avant de capturer l'état?

C'est à peu près ce que j'ai fait

private final LinkedList<String> extraTokens = new LinkedList<String>();
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private State savedState;

@Override
public boolean incrementToken() throws IOException {
    if (!extraTokens.isEmpty()) {
        // Do we not loose/overwrite the current termAtt token here? (*)
        restoreState(savedState);
        termAtt.setEmpty().append(extraTokens.remove());
        return true;
    }
    if (input.incrementToken()) {
        if (/* condition */) {
           extraTokens.add("fo");
           savedState = captureState();
        }
        return true;
    }
    return false;
}

Cela signifie-t-il, pour un flux d'entrée de chaîne de caractères à espace blanc "a b c"

 (a) -> (b) -> (c) -> ...

bb est un nouveau synonyme de b, que le graphique sera construit comme ça quand restoreState est utilisé?

    (a)
   /   \
(b)    (bb)
   \   /
    (c)
     |
    ...

2. Attributs

Vu le texte foo bar baz avec fo être la tige de foo et qux être synonyme de bar baz, ai-je construit la table attributaire correcte?

+--------+---------------+-----------+--------------+-----------+
|  Term  |  startOffset  | endOffset | posIncrement | posLenght |
+--------+---------------+-----------+--------------+-----------+
|  foo   |       0       |     3     |      1       |     1     |
|  fo    |       0       |     3     |      0       |     1     |
|  qux   |       4       |     11    |      0       |     2     |
|  bar   |       4       |     7     |      1       |     1     |
|  baz   |       8       |     11    |      1       |     1     |
+--------+---------------+-----------+--------------+-----------+

11
2017-07-04 18:54


origine


Réponses:


1.

Le fonctionnement de l’API basée sur les attributs est que chaque TokenStream dans votre chaîne d'analyse modifie en quelque sorte l'état de certains Attributes à chaque appel de incrementToken(). Le dernier élément de votre chaîne produit alors les jetons finaux.

Chaque fois que le client de votre analyseur chaîne appelle incrementToken(), le dernier TokenStream définirait l'état de certains Attributes à tout ce qui est nécessaire pour représenter le prochain jeton. S'il est incapable de le faire, il peut appeler incrementToken() sur son entrée, laisser le précédent TokenStream faire son travail Cela continue jusqu'au dernier TokenStream résultats false, indiquant que plus de jetons sont disponibles.

UNE captureState copie l'état de tous Attributes de l'appel TokenStream dans une State, une restoreState écrase chaque Attribute'état avec tout ce qui a été capturé avant (est donné en argument).

La façon dont votre filtre à jeton fonctionne est qu'il appellera input.incrementToken(), de sorte que le précédent TokenStream mettra le Attributes 'état à ce qui serait le prochain jeton. Ensuite, si votre condition définie est valide (par exemple, le termeAtt est "b"), cela ajoutera "bb" à une pile, sauvegardera cet état quelque part et renverra true afin que le client puisse consommer le jeton. Au prochain appel de incrementToken(), il n'utiliserait pas input.incrementToken(). Quel que soit l'état actuel, il représente le jeton précédent, déjà consommé. Le filtre restaure alors l'état, de sorte que tout se passe exactement comme avant, puis génère "bb" comme jeton actuel et renvoie true, de sorte que le client puisse consommer le jeton. Uniquement lors du prochain appel, il consomme (à nouveau) le prochain jeton du filtre précédent.

Cela ne produira pas réellement le graphique que vous avez affiché, mais insérez "bb" après "b", donc c'est vraiment

(a) -> (b) -> (bb) -> (c)

Alors, pourquoi sauvez-vous l'État en premier lieu? Lorsque vous produisez des jetons, vous voulez vous assurer, par exemple, que les requêtes de phrase ou de mise en évidence fonctionneront correctement. Quand tu as le texte "a b c" et "bb" est un synonyme de "b", vous attendez la requête phrase "b c" travailler, ainsi que "bb c". Vous devez dire à l'index que les deux "b" et "bb" sont dans la même position. Lucene utilise un incrément de position pour cela et par défaut, l’incrément de position est 1, ce qui signifie que chaque nouveau jeton (lecture, appel de incrementToken()) vient 1 position après la précédente. Ainsi, avec les positions finales, le flux produit est

(a:1) -> (b:2) -> (bb:3) -> (c:4)

alors que vous voulez réellement

(a:1) — -> (b:2)  -> — (c:3)
      \              /
        -> (bb:2) ->

Donc, pour que votre filtre produise le graphique, vous devez définir l’incrément de position sur 0 "bb"

private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
// later in incrementToken
restoreState(savedState);
posIncAtt.setPositionIncrement(0);
termAtt.setEmpty().append(extraTokens.remove());

le restoreState s'assure que les autres attributs, tels que les décalages, les types de jetons, etc., sont préservés et que vous n'avez qu'à modifier ceux qui sont requis pour votre cas d'utilisation. Oui, vous écrasez quel que soit l'état avant restoreState, il est donc de votre responsabilité de l’utiliser au bon endroit. Et tant que vous n'appelez pas input.incrementToken(), vous ne faites pas avancer le flux d'entrée, vous pouvez donc faire ce que vous voulez avec l'état.

2.

Un stemmer modifie uniquement le jeton, il ne produit généralement pas de nouveaux jetons ni ne modifie l'incrément de position ou les décalages. En outre, comme l’incrément de position signifie, le terme actuel devrait venir positionIncrement positions après le jeton précédent, vous devriez avoir qux avec un incrément de 1, car c'est le prochain jeton après of et bar devrait avoir un incrément de 0 car il est dans la même position que qux. La table ressemblerait plutôt

+--------+---------------+-----------+--------------+-----------+
|  Term  |  startOffset  | endOffset | posIncrement | posLenght |
+--------+---------------+-----------+--------------+-----------+
|  fo    |       0       |     3     |      1       |     1     |
|  qux   |       4       |     11    |      1       |     2     |
|  bar   |       4       |     7     |      0       |     1     |
|  baz   |       8       |     11    |      1       |     1     |
+--------+---------------+-----------+--------------+-----------+

En règle générale, pour les synonymes multi-termes, où "ABC" est synonyme de "a b c", vous devriez voir que

  • positionIncrement ("ABC")> 0 (l'incrément du premier jeton)
  • positionIncrement (*)> = 0 (les positions ne doivent pas reculer)
  • startOffset ("ABC") == startOffset ("a") et endOffset ("ABC") == endOffset ("c")
    • en fait, les jetons à la même position (début | fin) doivent avoir le même décalage (début | fin)

J'espère que cela aide à faire la lumière.


20
2017-11-19 19:44