2011-11-08 4 views
0

Le programme suivant:Lucene QueryParser comportement incohérent

import java.util.Arrays; 
import java.util.List; 

import org.apache.lucene.analysis.standard.StandardAnalyzer; 
import org.apache.lucene.queryParser.ParseException; 
import org.apache.lucene.queryParser.QueryParser; 
import org.apache.lucene.util.Version; 

public class LuceneTest { 

    static final List<Character> SPECIAL_CHARS = 
     Arrays.asList('\\', '+', '-', '!', '(', ')', ':', '^', '[', ']', '"', '{', '}', '~', '*', '?', '|', '&'); 

    public static void main(String[] args) throws ParseException { 
    QueryParser query = 
     new QueryParser(Version.LUCENE_31, "", new StandardAnalyzer(Version.LUCENE_31)); 


    for (char c : SPECIAL_CHARS) { 
     System.out.println(c + " -> " + query.parse("__catch_all:foo\\" + c + "bar").toString()); 
    } 
    } 

} 

donne cette sortie:

\ -> __catch_all:foo __catch_all:bar 
+ -> __catch_all:foo __catch_all:bar 
- -> __catch_all:foo __catch_all:bar 
! -> __catch_all:foo __catch_all:bar 
(-> __catch_all:foo __catch_all:bar 
) -> __catch_all:foo __catch_all:bar 
: -> __catch_all:foo:bar 
^ -> __catch_all:foo __catch_all:bar 
[ -> __catch_all:foo __catch_all:bar 
] -> __catch_all:foo __catch_all:bar 
" -> __catch_all:foo __catch_all:bar 
{ -> __catch_all:foo __catch_all:bar 
} -> __catch_all:foo __catch_all:bar 
~ -> __catch_all:foo __catch_all:bar 
* -> __catch_all:foo __catch_all:bar 
? -> __catch_all:foo __catch_all:bar 
| -> __catch_all:foo __catch_all:bar 
& -> __catch_all:foo __catch_all:bar 

Notez la contradiction apparente avec: et notez aussi que je suis échapper au caractère spécial (faire exactement même chose que QueryParser.escape). Je m'attends à ce que StandardAnalyzer supprime la ponctuation spéciale des termes de la requête, et cela dans presque tous les cas.

La raison pour laquelle cela semble particulièrement contradictoire est que la rédaction d'un document avec un StandardAnalyzer et un texte sur le terrain de « foo: bar » va me donner un deux champs terme, foo et bar! Un second cycle d'échappement donne le résultat correct, c'est-à-dire, "foo \\: bar"; mais pourquoi est-ce nécessaire seulement pour les deux-points? Pourquoi devrais-je besoin de faire QueryParser.escape (QueryParser.escape (mystring)) pour éviter ce comportement?

Répondre

0

La gestion différente de ':' n'est pas la faute de QueryParser mais de StandardAnalyzer. En fait, ':' est le seul caractère de votre liste qui n'est pas considéré comme un séparateur par StandardAnalyzer. En conséquence, l'analyse de "a: b" donnerait un jeton "a: b" alors que l'analyse "a'b" donnerait deux jetons "a" et "b".

Voici ce qui se passe:

Original String -> unescaped string -> tokens -> query

"foo\:bar" -> "foo:bar" -> [ "foo:bar" ] -> TermQuery(__catch_all, "foo:bar")

"foo\+bar" -> "foo+bar" -> [ "foo", "bar" ] -> TermQuery(__catch_all, "foo") OR TermQuery(__catch_all, "bar")

+0

C'est beaucoup d'informations, merci. Du côté de * write *, il semble que StandardAnalyzer tokenise la chaîne en tant que "foo bar", ce qui semble incohérent. – HenryR

+0

Qu'est-ce qui vous fait penser ainsi? Pouvez-vous fournir un morceau de code qui montre ce problème? – jpountz

Questions connexes