Elasticsearch ES|QL ermöglicht die Volltextsuche in Daten, die nie von Ihnen indiziert wurden.
MATCH und TO_TEXT ermöglichen die Volltextsuche in Daten, die nie von Ihnen indiziert wurden. So können Sie berechnete Spalten, nicht zugeordnete Felder und Verbunddaten in ES|QL durchsuchen.
Get hands-on with Elasticsearch: Dive into our sample notebooks in the Elasticsearch Labs repo, start a free cloud trial, or try Elastic on your local machine now.
ES|QL MATCH führt jetzt eine Volltextsuche auf Daten aus, die Sie nie indexiert haben. Berechnete Spalten, nicht zugeordnete Felder, spontan zusammengestellte Zeichenfolgen, sogar Verbunddaten, die in S3 gespeichert sind. Die neue Funktion TO_TEXT weist ES|QL an, jede Zeichenfolge als analysierbaren Text zu behandeln, sodass MATCH Werte tokenisieren, Groß-/Kleinschreibung auflösen und Terme abgleichen kann, die nur für die Dauer einer Abfrage existieren. Das geht über die LIKE- und RLIKE-Mustererkennung hinaus, die die meisten Abfrage-Engines für nicht indexierte Zeichenfolgen anbieten: Es handelt sich um echte Analyse. Jetzt verfügbar in Elastic Cloud Serverless und als technische Vorschau in Elasticsearch 9.5.
Wie MATCH und TO_TEXT die Volltextsuche in beliebigen ES|QL-Ausdrücken ermöglichen
Beginnen wir mit einer Abfrage, die in Elasticsearch 9.4 unmöglich war und den EVAL-Befehl verwendet:
FROM cooking_blog
| EVAL summary = TO_TEXT(CONCAT(title, description))
| WHERE MATCH(summary, "pancakes")
| KEEP title, authorIn diesem Beispiel hat Summary keine Mapping- oder Analyzer-Konfiguration. Es ist auch mit keinem invertierten Index verbunden. Es existiert nur für die Dauer dieser Abfrage, kann jetzt aber trotzdem durchsucht werden. Das machen zwei Ergänzungen möglich.
Erstens akzeptiert MATCH nun jeden Ausdruck als erstes Argument, nicht nur ein abgebildetes Feld. Dies umfasst Spalten, die von EVAL erzeugt werden, sowie Funktionsergebnisse, die inline verwendet werden. Es enthält auch nicht zugeordnete Felder, die direkt aus dem Originaldokument geladen wurden. Darüber hinaus werden in diesem neuen Anwendungsfall alle normalerweise von MATCH akzeptierten Datentypen unterstützt.
Der zweite Teil davon ist die neue TO_TEXT-Funktion, die die erste ES|QL-Konvertierungsfunktion ist, die eine Ausgabe vom Typ Text erzeugt. Bisher konnten Textspalten nur aus indizierten zugeordneten Feldern stammen, und alle von ES|QL-Ausdrücken erzeugten Zeichenfolgen waren Schlüsselwortwerte statt Textwerte. Die Unterscheidung ist wichtig, weil MATCH die beiden unterschiedlich behandelt: Textwerte werden analysiert, während Keyword-Werte exakt verglichen werden, was der Umschreibung einer MATCH-Abfrage auf einem indexierten Schlüsselwortfeld in eine Termanfrage ähnelt. TO_TEXT(x) ist die Art, wie Siew ES|QL Folgendes sagen: Behandle diese Zeichenfolge als Volltext.
Dies wird als technische Vorschau in Elasticsearch 9.5 ausgeliefert und hat daher einige Einschränkungen:
Es wird derzeit nur gefiltert. Ein MATCH-Ergebnis in einem Ausdruck trägt noch nicht zur Relevanzbewertung bei; nur Übereinstimmungen in indizierten Feldern wirken sich auf die Bewertung aus.
Abfrageoptionen wie Unschärfe und andere werden beim Abgleich eines Ausdrucks noch nicht unterstützt.
Der Laufzeittext wird mit dem Standard-Analyzer analysiert. Dies ist noch nicht konfigurierbar.
Es wird daran gearbeitet, diese Einschränkungen zu beheben.
Warum sollte man in ES|QL Volltextsuche statt LIKE oder RLIKE verwenden?
ES|QL hatte bereits zwei Möglichkeiten, Zeichenfolgen ohne Index zu suchen: LIKE (Wildcard-Muster) und RLIKE (reguläre Ausdrücke). Beide funktionieren bei jedem Zeichenfolge-Ausdruck, daher ist es fair zu fragen, was MATCH hinzufügt. Die Antwort ist analysis, eine fortgeschrittenere Suchmethode, die Techniken wie Stemming und Synonyme verwendet. Es verwendet auch eine Stoppwortbehandlung.
LIKE ist einfaches Substring-Matching, ohne jegliches Verständnis der Wörter, aus denen eine Zeichenfolge besteht. Nehmen wir beispielsweise an, Sie suchen nach Log-Meldungen über einen Fuchs:
FROM app_logs
| WHERE message LIKE "*fox*"„Fuchs in der Nähe des Hühnerstalls gesichtet“ wird aufgrund der Großschreibung nicht gefunden, während es „Von der Konkurrenz überlistet“ ein Treffer ist, obwohl das überhaupt nichts mit einem Fuchs zu tun hat. Das Verfahren versagt in beiden Richtungen: Es kommt zu falschen Negativbefunden bei der Großschreibung und zu falschen Positivbefunden bei innerhalb anderer Wörter verborgenen Teilzeichenfolgen.
Reguläre Ausdrücke können das Problem der Groß-/Kleinschreibung beheben, aber das Problem der Wortgrenzen wird schnell unübersichtlich. Hier ist ein Beispiel:
FROM app_logs
| WHERE message RLIKE "(.* )?[Ff][Oo][Xx]([ ,.:;].*)?"Und selbst das stimmt noch nicht. Der Fuchs am Ende eines Satzes, gefolgt von ! oder ?, ist ihm entgangen und es sagt nichts über Tabulatoren, Anführungszeichen oder Klammern aus. Mit jeder Korrektur wird das Muster länger, und die nächste Person, die die Abfrage liest, muss nachvollziehen, was das eigentlich passiert.
MATCH beseitigt das Problem, weil sowohl die Abfrage als auch der Wert durch einen Analyzer laufen, der den Text in Kleinbuchstaben tokenisiert und dann Term für Term abgleicht:
FROM app_logs
| WHERE MATCH(TO_TEXT(message), "fox")Diese Abfrage passt zu Werten wie „Der schnelle braune Fuchs“ und „FUCHS in der Nähe des Hühnerstalls gesehen“, aber nicht „Von der Konkurrenz überlistet“ oder „FOXTROT-Protokoll aktiviert“, unabhängig von jeglicher Zeichensetzung um die Wörter. Selbstverständlich funktioniert das alles auch für Abfragen mit mehreren Begriffen, wie z. B. MATCH(TO_TEXT(message), „brauner Fuchs“), genau so, wie man es erwarten würde.
Es wird daran gearbeitet, die Nutzung der 36 dedizierten Sprachanalysatoren zu ermöglichen, mit Unterstützung für natürliche Sprachen auf Daten, die nie indexiert oder kartiert wurden.
Anwendungsfälle der Volltextsuche für unindexierte und nicht abgebildete Daten
Die obigen Beispiele suchten Werte, die aus abgebildeten Feldern berechnet wurden. Die interessantesten Anwendungsfälle für ES|QL MATCH bei Ausdrücken betreffen Daten, die zuvor überhaupt nicht durchsuchbar waren. Schauen wir uns einige Beispiele an.
Wie kann man in ES|QL nach nicht zugeordneten Feldern suchen, ohne ein Mapping hinzuzufügen?
Manchmal lässt man absichtlich ein Feld aus den Mappings weg, wie zum Beispiel eine ausführliche Stack-Trace oder eine rohe Anfrage-Nutzlast. Du könntest sogar einen Debug-Blob weglassen. Das Indexieren eines dieser Felder würde Speicherplatz auf der Festplatte und im Heap-Speicher des Dokuments beanspruchen und wäre für ein Feld, das man möglicherweise nur einmal pro Quartal abfragt, nicht lohnenswert.
Diese Entscheidung war immer endgültig, weil nicht zugeordnete Felder für Abfragen völlig unsichtbar waren. In Elasticsearch 9.5 können Sie mit SET unmapped_fields="load" bewirken, dass ES|QL nicht zugeordnete Felder direkt aus dem Quelldokument als Schlüsselwörter lädt. Anschließend wird der Ausdruck in TO_TEXT eingeschlossen, und nun können Sie eine Volltextsuche darauf ausführen:
SET unmapped_fields="load";
FROM app_logs
| WHERE MATCH(TO_TEXT(stack_trace), "java.lang.NullPointerException")
| KEEP @timestamp, service.name, messageHier wurde stack_trace nie zugeordnet. Jeder Wert wird aus den Originaldokumenten abgerufen und direkt analysiert. Sie werden zeilenweise einander zugeordnet. Das ist echte Arbeit und wird niemals so schnell sein wie eine invertierte Index-Suche. Aber jetzt ist das Feld, das Sie nicht indexiert haben, nicht mehr undurchsuchbar. Sie können das Mapping für den Alltag klein halten und trotzdem die einmal im Quartal anstehende Frage beantworten, wenn es darauf ankommt.
Volltextsuche in einem Stichwortfeld ohne Neuindizierung
Keyword-Felder können vieles bewirken. Sie liefern exakte Abgleiche, schnelle Aggregationen und Sortierung, weshalb so viele Felder auf diese Weise zugeordnet werden. Die Mappings der Daten erfolgen jedoch erst, wenn sie eintreffen, und es kann leicht passieren, dass man am Ende etwas anderes mit den Daten machen möchte, als man ursprünglich beabsichtigt hatte. Vielleicht wurde „product_name“ als Keyword zugeordnet, weil die Dashboards darauf aggregieren, und nachdem ein Jahr Produktdaten eingegangen ist, möchte jemand innerhalb der Werte von „product_name“ suchen können.
Die alte Antwort war, das Mapping auf Text zu ändern (oder ein Multi-Feld hinzuzufügen) und alles neu zu indexieren. Das kann sowohl zeitaufwändig als auch kostspielig sein, und in vielen Fällen wollen sich die Nutzer einfach nicht darum kümmern. Die neue Antwort ist ein Funktionsaufruf:
FROM products
| WHERE MATCH(TO_TEXT(product_name), "wireless noise cancelling headphones")
| KEEP product_name, brand, priceTO_TEXT wandelt die Keyword-Werte spontan in Text um; daher analysiert MATCH sie, anstatt sie exakt zu vergleichen. So können Sie ein Schlüsselwort-Feld abfragen, ohne ein Mapping erstellen oder das Quelldokument neu zu indexieren. Wenn die Suche zu einer alltäglichen Anfrage wird, ist das Indizieren des Feldes als Text zwar immer noch der richtige langfristige Schritt, aber mit TO_TEXT erhalten Sie heute schon eine Antwort, ohne zusätzlichen Aufwand.
Das gleiche Feld in Indizes mit unterschiedlichen Mappings durchsuchen
ES|QL kann viele Indizes umfassen, und dasselbe Feld muss nicht immer in allen gleich aussehen. Wenn dasselbe Feld unterschiedliche Typen in verschiedenen Indizes hat, behandelt ES|QL es als Unionstyp, und eine Konvertierungsfunktion löst den Konflikt. Betrachten wir ein Beispiel, in dem das Message-Feld in der diesjährigen Indexvorlage den Typ „Text“ hat, in der letztjährigen Vorlage aber ein Keyword war:
FROM logs-2025, logs-2026
| EVAL msg = TO_TEXT(message)
| WHERE MATCH(msg, "connection reset")Jeder Wert wird zur Abfragezeit analysiert, unabhängig davon, ob er aus dem Textindex oder dem Stichwortindex stammt. Die Keywordwerte aus den älteren Indizes werden wie alles andere tokenisiert und kleingeschrieben, sodass „connection reset“ unabhängig davon, in welchem Index es sich befindet, „Connection RESET by peer“ findet.
Ein weiterer interessanter Fall ist, wenn ein Feld nur in einem Index abgebildet wird, aber auch im anderen vorhanden (und nicht abgebildet):
SET unmapped_fields="load";
FROM logs-2025, logs-2026
| WHERE MATCH(TO_TEXT(error_details), "timeout")Es gibt eine Nuance, die es wert ist, hier erwähnt zu werden. Wenn error_details in logs-2026, aber nicht in logs-2025 abgebildet ist, kann Elasticsearch diese Abfrage nicht auf Lucene verschieben, da die Indizes, in denen das Feld nicht abgebildet ist, stillschweigend keine Übereinstimmungen liefern würden. Stattdessen stellt der Planer fest, dass das Feld möglicherweise nicht zugeordnet ist und wertet die gesamte MATCH Zeile für Zeile aus, unabhängig davon, woher die Zeilen stammen. Sie müssen nicht wissen, in welchem Ihrer Indizes das Feld zugeordnet ist; die Abfrage beantwortet einfach die Frage.
Wie ES|QL Text zur Abfragezeit ohne invertierten Index analysiert
Wenn ES|QL einen MATCH-Abgleich mit einem Ausdruck plant, analysiert es die Abfragezeichenfolge einmalig, im Voraus, in eine Reihe von Begriffen. Wie jede Zeile anschließend ausgewertet wird, hängt vom Typ des Ausdrucks ab:
Ausdruckstyp | Verarbeitung | Übereinstimmendes Verhalten |
Text (über TO_TEXT) | Analyzer tokenisiert Werte in Kleinbuchstaben | Token-gegen-Token-Vergleich; eine Zeile gilt als Treffer, wenn ein Token einem Abfrageterm entspricht (ODER-Semantik) |
Schlüsselwort, IP, Datum, numerisch | Keine Analyse; die Abfragekonstante einmal in den nativen Typ konvertiert | Exakter Vergleich pro Zeile |
Beide Wege umgehen Lucene vollständig und bewerten Werte Zeile für Zeile. Der Nichttextpfad spiegelt genau das wider, was eine Match-Query tut, wenn sie an Lucene für diese Feldtypen delegiert wird, sodass die Semantik unabhängig davon konsistent bleibt, ob die Abfrage einen Index trifft.
Eine Suche mit invertiertem Index führt ihre Arbeit zur Ingest-Zeit durch und greift bei der Abfrage niemals auf nicht übereinstimmende Dokumente zu. Ein Laufzeit-Match führt diese Analyse zur Abfragezeit für jede Zeile durch, die sie erreicht. Die eine Methode ist schnell, weil die Arbeit bereits erledigt ist; die andere ist flexibel, weil die Daten überhaupt nicht indexiert werden müssen.
Was kommt als Nächstes für die ES|QL-Volltextsuche
Alles in diesem Beitrag ist der erste Teil eines größeren Vorhabens, die Suche in ES|QL auf alles anzuwenden, nicht nur auf das, was man vorher indexiert hat. Die zuvor genannten Einschränkungen werden aktiv bearbeitet und die Roadmap geht weiter:
Bewertung. Runtime-Matches tragen zu _score bei, sodass Sie nach Relevanz sortieren können, auch wenn die Daten nie indexiert wurden.
MATCH_PHRASE auf Ausdrücke. Bereits in Elastic Cloud Serverless verfügbar, und kommt im Elastic Stack in Version 9.6.
Konfigurierbare Analysatoren. Analyzer-Unterstützung für MATCH und MATCH_PHRASE bei Ausdrücken, die Language Analyzer, Stemming und Synonyme zur Abfragezeit ermöglichen.
Matchoptionen. Optionen wie Unschärfe und Operator für Laufzeitübereinstimmungen.
Vektorsuche. Generieren von Einbettungen pro Zeile und Ausführen der k-Nearest-Neighbor-Methode (kNN) auf Laufzeit-dense_vector-Ausdrücken, wodurch die semantische Suche auch auf unindizierte Daten ausgeweitet wird.
Probieren Sie noch heute die ES|QL-Volltextsuche für Ausdrücke aus.
Sie können die Laufzeitsuche noch heute ausprobieren. Es ist jetzt in Elastic Cloud Serverless verfügbar, wo neue ES|QL-Fähigkeiten zuerst erscheinen und als technische Vorschau in Elasticsearch 9.5 ausgeliefert werden. Beginnen Sie mit der Suchfunktionsreferenz und prüfen Sie die ES|QL-Einschränkungsseite für die aktuellen Grenzen. Es ist eine technische Vorschau, weil wir Ihr Feedback wollen: Wenn Sie nach etwas suchen, das nie indexiert wurde, und überrascht, sei es positiv oder negativ, würden wir gerne davon hören.
Zugehörige Inhalte




