2013-07-24 4 views
17

Hier ist die Sache. Ich habe einen Begriff im Index gespeichert, die Sonderzeichen, wie enthält ‚-‘, ist die einfachste Code wie folgt:Wie führe ich mit QueryParser eine Lucene-Abfrage mit Sonderzeichen aus?

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

Und dann erstelle ich eine Abfrage mit QueryParser, wie folgt aus:

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

Und dann benutze ich einen Sucher, um die Abfrage zu suchen und kein Ergebnis zu erhalten. Ich habe es auch versucht:

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

Und immer noch kein Ergebnis.

Ohne Verwendung von QueryParser und stattdessen mit TermQuery direkt tun können, was ich will, aber dieser Weg ist nicht flexibel genug für Benutzereingabetexte.

Ich denke, dass der StandardAnalyzer etwas getan hat, um das Sonderzeichen in der Abfragezeichenfolge wegzulassen. Ich habe versucht, debuggen, und ich fand, dass die Zeichenfolge aufgeteilt ist und die tatsächliche Abfrage lautet wie folgt: "Nachricht: 1111 Nachricht: 2222 Nachricht: 3333". Ich weiß nicht, was genau Lucene getan hat ...

Also, wenn ich die Abfrage mit Sonderzeichen ausführen möchte, was soll ich tun? Sollte ich einen Analysator neu schreiben oder einen Abfrageparser vom Standard-Erben übernehmen? Und wie man ...

Update:?

1 @The New-Idiot @femtoRgon, ich habe versucht, QueryParser.escape (queryStr), wie in dem Problem angegeben, aber es funktioniert immer noch nicht.

2 Ich habe einen anderen Weg versucht, das Problem zu lösen. Ich habe einen QueryTokenizer aus Tokenizer abgeleitet und das Wort nur nach Leerzeichen ausgeschnitten, in einen QueryAnalyzer gepackt, der von Analyzer abgeleitet ist, und schließlich den QueryAnalyzer an QueryParser übergeben.

Jetzt funktioniert es. Ursprünglich funktioniert es nicht, weil der standardmäßige StandardAnalyzer den queryStr nach Standardregeln schneidet (die einige der Sonderzeichen als Teiler erkennen), wenn die Abfrage in QueryParser übergeben wird, werden die Sonderzeichen bereits von StandardAnalyzer gelöscht. Jetzt benutze ich meinen eigenen Weg, um queryStr auszuschneiden und es erkennt nur den Platz als Splitter, also bleiben die Sonderzeichen in der Abfrage und warten auf die Verarbeitung, und das funktioniert.

3 @Der neue Idiot @femtoRgon, danke für die Beantwortung meiner Frage.

+1

Entschuldigung, ich habe offensichtlich nicht sorgfältig genug gelesen. Ich bin jedoch verwirrt: Woher kommt dieses 'TextField'? Lucenes 'TextField' nimmt kein' Field.Index'-Argument ('Field.Index' ist veraltet). Um ein Feld wie das, das Sie hier haben, zu erstellen, verwenden Sie stattdessen ein 'StringField'. Ist das eine Art benutzerdefiniertes 'TextField' oder etwas? – femtoRgon

+0

Entschuldigung, das ist meine Schuld. Ich benutze Lucene 3.6 und es gibt kein TextField in Lucene 3.x. Der richtige Code sollte lauten: 'doc.add (neues Feld (" message "," 1111-2222-3333 ", Field.Store.YES, Field.Index.NOT_ANALYZED));' Lucene 4.x- und 3.x-APIs sind sehr unterschiedlich, ich versuche immer noch Lucene 4.x APIs zu verstehen. –

+0

Ah, macht mehr Sinn. Etwas abseits, aber wenn Sie versuchen, die Änderungen in 4.x in den Griff zu bekommen, haben Sie sich den [Migrationsleitfaden] (http://lucene.apache.org/core/4_0_0/MIGRATE.html) angeschaut? Es ruft die wichtigsten Änderungen auf und liefert einige Gründe dafür. – femtoRgon

Antwort

19

Ich bin mir nicht sicher, aber ich denke, Sie müssen - mit \ entkommen. Gemäß der Lucene docs.

Der Operator "-" oder "verbieten" schließt Dokumente aus, die den Begriff nach dem Symbol "-" enthalten.

Wieder

Lucene unterstützt Sonderzeichen entweicht, der Teil der Abfrage-Syntax sind. Die aktuellen Sonderzeichen der Liste sind

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

Um diese Zeichen zu umgehen, verwenden Sie \ vor dem Zeichen.

Denken Sie auch daran, einige Zeichen müssen Sie zweimal entkommen, wenn sie eine besondere Bedeutung in Java haben.

+0

Danke für die Beantwortung, ich habe einen Weg gefunden, dies zu lösen, siehe mein Update. –

+1

Vergiss nicht, dass ab "Lucene 4.0" auch "/" ein Sonderzeichen (in Regex) ist. –

0

Sie können den Wert als addValue() anstelle von add oder addText hinzufügen. und suchen Sie dann im Sonderzeichen mit einem KyewordAnalyzer anstelle von Standard Analyzer. oder Fügen Sie die Daten mit addValue() hinzu und ersetzen Sie das Sonderzeichen bei der Suche nach Daten in luke durch das Platzhalterzeichen (?). Ich habe beide Möglichkeiten versucht und funktioniert

Verwandte Themen