Hervorhebung von Wildcard-Abfragen in Solr 1.4
Solr 1.3 und 1.4 verwenden für MultiTerm-Abfragen nicht mehr die BooleanQuery-Erweiterung, sondern eine ConstantScoreQuery-Methode. In Lucene ist eine MultiTerm-Abfrage eine Abfrage, die so erweitert wird, dass sie mit mehreren Begriffen auf der Grundlage einer bestimmten Eingabe übereinstimmt. Übliche MultiTerm-Abfragen sind Wildcard-, Fuzzy-, Präfix- und Bereichsabfragen. Ursprünglich unterstützte Lucene diese MultiTerm-Abfragen mit einer Implementierung, bei der die übereinstimmenden Begriffe aufgezählt und dann jeweils als Klausel zu einer BooleanQuery hinzugefügt wurden. Dies ist ein gängiger Ansatz, der jedoch einige Probleme mit sich bringt. Eine BooleanQuery mit Tausenden von Begriffen ist wahrscheinlich nicht sehr leistungsfähig. Als Vorsichtsmaßnahme gegen diese Leistungsfalle werfen Boolean-Expansionsabfragen bei einem Standardwert von 1024 Klauseln eine TooManyClauses-Ausnahme. Dies ist eine konfigurierbare Einstellung, aber das zugrunde liegende Leistungsproblem bleibt bestehen, wenn Sie sie erhöhen.
Als Reaktion auf diese Leistungsfalle bei sehr großen Indizes (und die berüchtigte TooManyClauses-Ausnahme) wurden neue Abfragen entwickelt, die sich auf eine neue Abfrageklasse namens ConstantScoreQuery stützen. ConstantScoreQuerys akzeptieren einen Filter mit übereinstimmenden Dokumenten und bewerten dann mit einem konstanten Wert, der dem Boost entspricht. Je nach den Eigenschaften Ihres Index kann diese Methode schneller sein als die Methode der booleschen Expansion und, was noch wichtiger ist, sie leidet nicht unter TooManyClauses-Ausnahmen. Anstatt n BooleanQuery-Klauseln (potenziell Tausende von Klauseln) abzugleichen und zu bewerten, wird ein einziger Filter aufgezählt und dann für die Bewertung weitergereist. Andererseits ist das Erstellen und Bewerten mit einer BooleanQuery, die einige Klauseln enthält, wahrscheinlich viel schneller als das Erstellen und Durchlaufen eines Filters.
Je nach den Merkmalen Ihres Index kann eine der beiden Methoden schneller sein als die andere. Längerfristig hoffen wir, dass wir MultiTerm-Abfragen haben werden, die eine Heuristik verwenden, um zu entscheiden, welche Methode zu verwenden ist. Der erste Schritt wird wahrscheinlich darin bestehen, eine effiziente ConstantScore BooleanQuery zu erstellen, da Sie nicht wollen, dass sich das Scoring auf magische Weise ändert, wenn Sie verschiedene Heuristiken treffen.
In jedem Fall ist Solr mit Solr 1.3 dazu übergegangen, ConstantScoreQueries für Range-, Wildcard- und Präfix-Abfragen zu verwenden. Das machte die Sache für die großen Indexinstallationen da draußen etwas angenehmer (keine TooManyClauses-Ausnahmen mehr, um die man sich sorgen müsste), aber es gab ein Opfer – während alle diese Abfragen vorher hervorgehoben werden konnten, war das nach dieser Änderung nicht mehr der Fall. Der Lucene Highlighter war noch nie in der Lage, ConstantScore-Abfragen hervorzuheben, da er sich darauf verlässt, dass die Abfrage in der Lage ist, die übereinstimmenden Begriffe zu liefern oder in eine Abfrage umzuschreiben, die das kann – ConstantScore-Abfragen tun beides nicht. Solr verwendet natürlich den Lucene Highlighter unter der Haube.
Um die richtige Hervorhebung wieder in Solr einzubauen, musste ich auf die Lucene-Ebene gehen und dafür sorgen, dass die MultiTerm-Abfragen alle zwischen boolescher Expansion und konstantem Score-Modus umgeschaltet werden können. Bis dahin hatten eine Handvoll der MultiTerm-Abfragen eine separate ConstantScoreQuery-Implementierung (z.B. PrefixQuery und ConstantScorePrefixQuery) und einige hatten keine ConstantScore-Implementierung. Nachdem ich die Dinge so geändert hatte, dass alle MultiTerm-Abfragen in einem einzigen Query-Objekt zwischen dem booleschen und dem ConstantScore-Modus umgeschaltet werden konnten, konnte ich den Lucene SpanScorer Highlighter so modifizieren, dass er beim Durchlaufen des Query-Objekts nach einer MultiTerm-Abfrageinstanz sucht, eine Kopie davon anfertigt, die Kopie auf den booleschen Expansionsmodus setzt und sie gegen einen MemoryIndex umschreibt, der nur das hervorzuhebende Dokument enthält. Während die Abfrage also als ConstantScore-Abfrage auf den Index angewendet wird, wird der Highlighter eine Kopie der Abfrage in den Booleschen Expansionsmodus versetzen und die Begriffe aus der umgeschriebenen Abfrage abrufen (die eine hervorhebbare Boolesche Abfrage sein wird). Obwohl die beiden Modi unterschiedliche Ergebnisse liefern, werden sie die gleichen Begriffe finden. Sie haben zwar immer noch mit einem möglichen TooManyClauses-Problem zu kämpfen, wenn Sie den Highlighter verwenden, aber das Problem wird stark entschärft, da die Abfrage nur für das einzelne hervorgehobene Dokument umgeschrieben wird und nicht für den gesamten Index. Es sollte auch nicht zu den gleichen Leistungsproblemen kommen, da die Abfrage nie auf den gesamten Index angewendet wird, sondern nur auf ein einzelnes Dokument (und dann wird nur getSpans aufgerufen).
Nachdem ich diese Änderungen in Lucene vorgenommen hatte, konnte ich die Korrektur in Solr übernehmen. Die Korrektur setzt voraus, dass Sie den PhraseHighlighter-Modus verwenden (hl.usePhraseHighlighter verwendet den Lucene SpanScorer) und dass Sie, um Kompatibilitätsprobleme zu vermeiden, angeben, dass der Highlighter intelligent mit dem SpanScorer umschreiben soll und nicht nur einmal im gesamten Index, bevor er markiert. Ich habe diese Option hl.highlightMultiTerm genannt und sie funktioniert nur in Verbindung mit hl.usePhraseHighlighter.
hl.usePhraseHighlighter=true
hl.highlightMultiTerm=true
Wenn Sie diese beiden Parameter auf true setzen, können Sie in Solr 1.4 wieder Wildcard-Abfragen hervorheben, zusammen mit allen anderen MultiTerm-Abfragen.