2013-07-24 18 views
17

Ecco la cosa. Ho un termine memorizzato nell'indice, che contiene caratteri speciali, come ad esempio '-', il codice più semplice è come questo:Come eseguire una query lucene contenente caratteri speciali utilizzando QueryParser?

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

E poi creare una query utilizzando QueryParser, in questo modo:

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

E quindi utilizzo un utente per cercare la query e non ottenere risultati. Ho anche provato questo:

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

E ancora nessun risultato.

Senza utilizzare QueryParser e invece utilizzando direttamente TermQuery può fare ciò che voglio, ma in questo modo non è abbastanza flessibile per i testi di input dell'utente.

Penso che forse lo StandardAnalyzer abbia fatto qualcosa per omettere il carattere speciale nella stringa di query. Ho provato il debug, e ho scoperto che la stringa è divisa e la query effettiva è simile a questa: "messaggio: 1111 messaggio: 2222 messaggio: 3333". Non so cosa abbia fatto esattamente lucene ...

Quindi, se voglio eseguire la query con carattere speciale, cosa devo fare? Dovrei riscrivere un analizzatore o ereditare un queryparser da quello predefinito? E come ...

Update:?

1 @The nuovo Idiota @femtoRgon, ho provato QueryParser.escape (queryStr) come indicato nel problema, ma ancora non funziona.

2 Ho provato un altro modo per risolvere il problema. Ho derivato un QueryTokenizer da Tokenizer e ho tagliato la parola solo per spazio, lo ho inserito in un oggetto QueryAnalyzer, che deriva da Analyzer, e infine ho passato QueryAnalyzer in QueryParser.

Ora funziona. Originariamente non funziona perché il default StandardAnalyzer taglia queryStr in base alle regole predefinite (che riconoscono alcuni caratteri speciali come splitter), quando la query viene passata in QueryParser, i caratteri speciali sono già cancellati da StandardAnalyzer. Ora uso il mio modo per tagliare queryStr e riconosce solo lo spazio come splitter, quindi i caratteri speciali rimangono nella query in attesa di elaborazione e questo funziona.

3 @The New Idiot @femtoRgon, grazie per aver risposto alla mia domanda.

+1

Mi scuso, ovviamente non ho letto abbastanza attentamente. Sono confuso però: da dove proviene questo 'TextField'? 'TextField' di Lucene non accetta un argomento' Field.Index' ('Field.Index' è deprecato). Per creare un campo come quello che hai qui, dovresti usare un 'StringField'. Si tratta di una sorta di "campo di testo" personalizzato o qualcosa del genere? – femtoRgon

+0

Mi dispiace, è colpa mia. Sto usando Lucene 3.6 e non c'è TextField in Lucene 3.x. Il codice corretto dovrebbe essere: 'doc.add (nuovo campo (" messaggio "," 1111-2222-3333 ", Field.Store.YES, Field.Index.NOT_ANALYZED));" Lucene 4.xe 3.x API sono molto diversi, sto ancora cercando di capire le API di lucene 4.x. –

+0

Ah, ha più senso. Un po 'fuori tema, ma se stai cercando di gestire le modifiche in 4.x hai guardato la [guida alla migrazione] (http://lucene.apache.org/core/4_0_0/MIGRATE.html)? Richiama i principali cambiamenti, oltre a fornire alcune motivazioni. – femtoRgon

risposta

19

Non sono sicuro di questo, ma suppongo che sia necessario sfuggire a - con \. Secondo lo Lucene docs.

L'operatore "-" o l'operatore di divieto esclude i documenti che contengono il termine dopo il simbolo "-".

Anche in questo caso,

Lucene supporta sfuggire caratteri speciali che fanno parte della sintassi di query. I caratteri speciali dell'elenco corrente sono

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

Per uscire da questi caratteri, utilizzare \ prima del carattere.

Ricorda inoltre, alcuni caratteri che dovrai sfuggire due volte se hanno un significato speciale in Java.

+0

Grazie per aver risposto, ho trovato un modo per risolvere questo problema, vedo il mio aggiornamento. –

+1

Non dimenticare che a partire da Lucene 4.0 "/" è anche un carattere speciale (utilizzato nella regex). –

0

è possibile aggiungere il valore come addValue() anziché aggiungere o aggiungere testo. e quindi cercare nel carattere speciale con un KyewordAnalyzer invece di Standard Analyzer. o Aggiungere i dati con addValue() e durante la ricerca dei dati in luke, sostituire il carattere speciale con il carattere di ricerca con caratteri jolly (?). Ho provato entrambi i modi e funziona

Problemi correlati