Frage

Bei meinen Tests bin ich plötzlich auf die Ausnahme „Zu viele Klauseln“ gestoßen, als ich versucht habe, die Treffer einer booleschen Abfrage abzurufen, die aus einer Termabfrage und einer Platzhalterabfrage bestand.

Ich habe im Internet nach den gefundenen Ressourcen gesucht und vorgeschlagen, BooleanQuery.SetMaxClauseCount() zu erhöhen.
Das klingt für mich faul..Auf was soll ich es erhöhen?Wie kann ich sicher sein, dass diese neue magische Zahl für meine Anfrage ausreicht?Wie weit kann ich diese Zahl erhöhen, bevor die Hölle losbricht?

Generell halte ich das für keine Lösung.Es muss ein tieferes Problem geben.

Die Abfrage lautete +{+companyName:mercedes +paintCode:a*} und der Index enthält ca. 2,5 Millionen Dokumente.

War es hilfreich?

Lösung

Der PaintCode: Ein* Teil der Abfrage ist eine Präfix -Abfrage für jeden Paintcode, der mit einem "a" beginnt. Ziehen Sie das an?

Lucene erweitert Präfixabfragen in eine boolesche Abfrage, die alle möglichen Begriffe enthält, die dem Präfix entsprechen. In Ihrem Fall sind anscheinend mehr als 1024 möglich paintCodes, die mit einem "a" beginnen.

Wenn es Ihnen so klingt, als ob Präfixabfragen nutzlos sind, sind Sie nicht weit von der Wahrheit entfernt.

Ich würde vorschlagen, dass Sie Ihr Indexierungsschema ändern, um eine Präfixabfrage zu vermeiden. Ich bin mir nicht sicher, was Sie mit Ihrem Beispiel erreichen möchten, aber wenn Sie nach dem ersten Buchstaben nach Lackcodes suchen möchten, machen Sie ein PaintCodeFirSTRetter -Feld und suchen Sie nach diesem Feld.

HINZUGEFÜGT

Wenn Sie verzweifelt sind und bereit sind, Teilergebnisse zu akzeptieren, können Sie Ihre eigene Lucene -Version aus der Quelle erstellen. Sie müssen Änderungen an den Dateien vornehmen PrefixQuery.java und MultiTermQuery.java, beide unter org/apache/lucene/search. In dem rewrite Methode beider Klassen, ändern Sie die Linie

query.add(tq, BooleanClause.Occur.SHOULD);          // add to query

zu

try {
    query.add(tq, BooleanClause.Occur.SHOULD);          // add to query
} catch (TooManyClauses e) {
    break;
}

Ich habe das für mein eigenes Projekt getan und es funktioniert.

Wenn Sie die Idee, Lucene zu wechseln, nicht mögen, können Sie Ihre eigene Präfixquery -Variante und Ihren eigenen Queryparser schreiben, aber ich denke nicht, dass es viel besser ist.

Andere Tipps

Es scheint, als würden Sie dies auf einem Feld verwenden, das eine Art ist Stichwort Typ (was bedeutet, dass Ihr Datenquellenfeld nicht mehrere Token enthält).

Hier gibt es einen Vorschlag, der mir ziemlich elegant erscheint: http://grokbase.com/t/lucene.apache.org/java-user/2007/11/substring-indexing-to-avoid-toomanyclauses-Exception/12f7s7kzp2emktbn66tdmfpcxfya

Die Grundidee besteht darin, Ihren Begriff in mehrere Felder mit zunehmender Länge aufzuteilen, bis Sie ziemlich sicher sind, dass Sie die Klauselbeschränkung nicht erreichen.

Beispiel:

Stellen Sie sich einen PaintCode wie diesen vor:

"a4c2d3"

Wenn Sie diesen Wert indizieren, erstellen Sie die folgenden Feldwerte in Ihrem Dokument:

[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"

Wenn Sie eine Abfrage durchführen, entscheidet die Anzahl der Zeichen in Ihrem Begriff darüber, in welchem ​​Feld gesucht werden soll.Dies bedeutet, dass Sie eine Präfixabfrage durchführen nur für Begriffe mit mehr als 3 Zeichen, was die interne Ergebnisanzahl erheblich verringert und das Berüchtigte verhindert TooManyBooleanClausesException.Offenbar beschleunigt dies auch den Suchvorgang.

Sie können ganz einfach einen Prozess automatisieren, der die Begriffe automatisch aufschlüsselt und die Dokumente bei der Indizierung nach einem Namensschema mit Werten füllt.

Wenn Sie für jedes Feld mehrere Token haben, können einige Probleme auftreten.Weitere Details finden Sie im Artikel

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top