2009-10-12 12 views
5

Ich habe einen Lucene-Index, der Dokumente enthält, die ein "type" -Feld haben, dieses Feld kann einen der drei Werte "article", "forum" oder " Blog ". Ich möchte, dass der Benutzer innerhalb dieser Typen suchen kann (es gibt ein Kontrollkästchen für jeden Dokumenttyp)Lucene Query - "Entsprechen genau eines von x, y, z"

Wie erstelle ich eine Lucene-Abfrage abhängig davon, welche Typen der Benutzer ausgewählt hat?

Ein paar Voraussetzungen sind:

  • Wenn der Benutzer nicht einer der Typen auswählt, ich will keine Ergebnisse von diesem Typ.
  • Die Reihenfolge der Ergebnisse sollte nicht durch Einschränkung des Typfeldes beeinflusst werden.

als Referenz, wenn ich dies in SQL schreiben war (für ein „Blog oder Forum search“) schreibe ich würde:

SELECT * FROM Docs 
WHERE [type] in ('blog', 'forum') 

Antwort

4

Als Referenz sollte sonst jemand über dieses Problem kommen, hier ist meine Lösung:

IList<string> ALL_TYPES = new[] { "article", "blog", "forum" }; 
string q = ...; // The user's search string 
IList<string> includeTypes = ...; // List of types to include 
Query searchQuery = parser.Parse(q); 
Query parentQuery = new BooleanQuery(); 
parentQuery.Add(searchQuery, BooleanClause.Occur.SHOULD); 
// Invert the logic, exclude the other types 
foreach (var type in ALL_TYPES.Except(includeTypes)) 
{ 
    query.Add(
     new TermQuery(new Term("type", type)), 
     BooleanClause.Occur.MUST_NOT 
    ); 
} 
searchQuery = parentQuery; 

ich die Logik invertiert (dh ausgeschlossen, die Arten der Benutzer nicht ausgewählt hatte), denn wenn man nicht das tun Die Reihenfolge der Ergebnisse ist verloren. Ich bin mir nicht sicher warum, aber ...! Es ist eine Schande, da es den Code weniger klar/wartbar macht, aber zumindest funktioniert es!

3

einen Zwang Hinzufügen von Dokumenten abzulehnen, die nicht ausgewählt wurden. wenn nur „Artikel“ So wurde zum Beispiel geprüft, würde die Einschränkung seine

-(type:forum type:blog) 
+0

Dies ist, was ich am Ende getan habe, obwohl ich die API verwendet habe, anstatt es als String zu erstellen, siehe meine Antwort, wenn Sie interessiert sind. – thatismatt

0

Während Erickson Vorschlag fein scheint, könnten Sie eine positive Einschränkung mit Ihrem Suchbegriff verknüpft verwenden, wie text:foo AND type:article für den Fall nur „Artikel“ wurde geprüft, oder text:foo AND (type:article OR type:forum) für den Fall sowohl "Artikel" und "Forum" überprüft wurden.

+0

Faszinierend die beiden Abfragen "Text: foo AND (Typ: Artikel OR Typ: Forum)" und "Text: foo UND-Typ: Blog" geben nicht die gleichen Ergebnisse, die erste Abfrage gibt die Blogs zuerst zurück, wo als zweite Query verwaltet die Reihenfolge (dh Blogs und Artikel sind gemischt). Irgendeine Idee warum? – thatismatt

+0

Lucene hat keinen "UND" -Operator. Es hat Operatoren + (erforderlich) und - (verbietet). – erickson

+0

@erickson: Ich bitte um Unterschiede: z.B. http://incubator.apache.org/lucene.net/docs/2.1/Lucene.Net.QueryParsers.QueryParser.AND_OPERATOR.html –

Verwandte Themen