web-dev-qa-db-fra.com

Comment effectuer une requête lucene contenant un caractère spécial en utilisant QueryParser?

Voici la chose. J'ai un terme stocké dans l'index, qui contient des caractères spéciaux, tels que '-', le code le plus simple est le suivant:

Document doc = new Document();
doc.add(new TextField("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);

Et puis je crée une requête en utilisant QueryParser, comme ceci:

String queryStr = "1111-2222-3333";
QueryParser parser = new QueryParser(Version.LUCENE_36, "message", new StandardAnalyzer(Version.LUCENE_36));
Query q = parser.parse(queryStr);

Et puis j'utilise un chercheur pour rechercher la requête et obtenir aucun résultat. J'ai aussi essayé ceci:

Query q = parser.parse(QueryParser.escape(queryStr));

Et toujours pas de résultat. 

Sans utiliser QueryParser mais plutôt avec TermQuery directement, vous pouvez faire ce que je veux, mais cette façon n’est pas assez souple pour les textes saisis par l’utilisateur.

Je pense que StandardAnalyzer a peut-être omis de supprimer le caractère spécial de la chaîne de requête. J'ai essayé le débogage, et j'ai trouvé que la chaîne est divisée et la requête réelle est comme ceci: "message: 1111 message: 2222 message: 3333". Je ne sais pas ce que Lucene a fait exactement ...

Donc, si je veux effectuer la requête avec un caractère spécial, que dois-je faire? Dois-je réécrire un analyseur ou hériter d'un interrogateur de celui par défaut? Et comment faire? ...

Mettre à jour:

1 @ The New Idiot @femtoRgon, j'ai essayé QueryParser.escape (queryStr) comme indiqué dans le problème, mais cela ne fonctionne toujours pas.

2 J'ai essayé un autre moyen de résoudre le problème. J'ai dérivé un QueryTokenizer de Tokenizer et ai découpé le mot uniquement par espace, que vous l'avez emballé dans un QueryAnalyzer, qui dérive d'Analyzer, puis que j'ai finalement transmis QueryAnalyzer à QueryParser. 

Maintenant ça marche. À l'origine, cela ne fonctionnait pas car StandardAnalyzer par défaut coupait le paramètre queryStr conformément aux règles par défaut (qui reconnaissent certains des caractères spéciaux comme séparateurs). Lorsque la requête est transmise à QueryParser, les caractères spéciaux sont déjà supprimés par StandardAnalyzer. Maintenant, j'utilise ma propre méthode pour couper le paramètre queryStr et il ne reconnaît que l'espace en tant que séparateur. Les caractères spéciaux restent donc dans la requête en attente de traitement et cela fonctionne.

3 @ The New Idiot @femtoRgon, merci d'avoir répondu à ma question.

19
Yuanchao Tang

Je ne suis pas sûr de cela, mais je suppose que vous devez vous échapper de - avec \. Selon les Lucene docs .

L'opérateur "-" ou interdire exclut les documents contenant le terme après le symbole "-".

Encore ,

Lucene prend en charge les caractères spéciaux d'échappement qui font partie de la syntaxe de la requête. Les caractères spéciaux de la liste actuelle sont

+ - && || ! () {} [] ^ "~ *?:\/

Pour échapper à ces caractères, utilisez\avant le caractère.

Rappelez-vous également que vous devrez échapper deux fois à certains caractères s'ils ont une signification particulière en Java.

21
NINCOMPOOP

vous pouvez ajouter la valeur addValue () à la place de add ou addText. puis recherchez le caractère spécial avec un KyewordAnalyzer au lieu de Standard Analyzer . ou Ajoutez les données avec addValue () et, tout en recherchant les données dans luke, remplacez le caractère spécial par le caractère de recherche générique (?) . J'ai essayé les deux manières et fonctionne

0
Shrek