DataPrime betreiber
Dieser Leitfaden enthält ein Glossar der Operatoren von IBM® Cloud Logs DataPrime.
block
Die Negation von filter. Filtert alle Ereignisse aus, bei denen die Bedingung erfüllt ist. Der gleiche Effekt kann durch die Verwendung von filter mit !(condition) erzielt werden.
block $d.status_code >= 200 && $d.status_code <= 299 # Leave all events which don't have a status code of 2xx
Die Daten werden in den folgenden Feldern angezeigt:
-
$m - Ereignis-Metadaten
timestampseverity- Mögliche Werte sindVerbose,Debug,Info,Warning,Error,Criticalpriorityclass- Mögliche Werte sindhigh,medium,lowlogid
-
$l - Ereignisbezeichnungen
applicationnamesubsystemnamecategoryclassnamecomputernamemethodnamethreadidipaddress
-
$d -Die Daten des Benutzers
bottom
Keine Gruppierungsvariante: Begrenzt die zurückgegebenen Zeilen auf eine bestimmte Anzahl und ordnet das Ergebnis nach einer Reihe von Ausdrücken.
order_direction := "descending"/"ascending" according to top/bottom
bottom <limit> <result_expression1> [as <alias>] [, <result_expression2> [as <alias2>], ...] by <orderby_expression> [as alias>]
Beispielsweise sollte die Abfrage
bottom 5 $m.severity as $d.log_severity by $d.duration
Führt zu Protokollen der folgenden Form:
[
{ "log_severity": "Debug", "duration": 1000 }
{ "log_severity": "Warning", "duration": 2000 },
...
]
Gruppierungsvariation: Begrenzt die zurückgegebenen Zeilen auf eine bestimmte Anzahl und gruppiert sie nach einer Reihe von Aggregationsausdrücken und ordnet sie nach einer Reihe von Ausdrücken.
order_direction := "descending"/"ascending" according to top/bottom
bottom <limit> <(groupby_expression1|aggregate_function1)> [as <alias>] [, <(groupby_expression2|aggregate_function2)> [as <alias2>], ...] by <(groupby_expression1|aggregate_function1)> [as <alias>]
Beispielsweise sollte die Abfrage
bottom 10 $m.severity, count() as $d.number_of_severities by avg($d.duration) as $d.avg_duration
Führt zu Protokollen der folgenden Form:
[
{ "severity": "Warning", "number_of_severities": 50, avg_duration: 1000 },
{ "severity": "Debug", "number_of_severities": 10, avg_duration: 2000 }
...
]
Die unterstützten Aggregationsfunktionen sind im Abschnitt "Aggregationsfunktionen" aufgeführt.
choose
Lassen Sie nur die vorgesehenen Tastenwege stehen und verwerfen Sie alle anderen Tasten. Vollständige Unterstützung verschachtelter Schlüsselpfade in der Ausgabe.
(choose|select) <keypath1> [as <new_keypath>],<keypath2> [as <new_keypath>],...
Beispiele:
choose $d.mysuperkey.myfield
choose $d.my_superkey.mykey as $d.important_value, 10 as $d.the_value_ten
convert
Konvertieren Sie die Datentypen der Schlüssel.
Das Schlüsselwort datatypes ist optional und kann zur besseren Lesbarkeit verwendet werden.
(conv|convert) [datatypes] <keypath1>:<datatype1>,<keypath2>:<datatype2>,...
Beispiele:
convert $d.level:number
conv datatypes $d.long:number,$d.lat:number
convert $d.data.color:number,$d.item:string
count
Gibt eine einzelne Zeile zurück, die die Anzahl der von den vorangegangenen Operatoren erzeugten Zeilen enthält.
count [into <keypath>]
Ein Alias kann angegeben werden, um den Tastaturpfad zu überschreiben, in den das Ergebnis geschrieben werden soll.
Zum Beispiel der folgende Teil einer Abfrage:
count into $d.num_rows
Das Ergebnis ist eine einzelne Zeile der folgenden Form:
{ "num_rows": 7532 }
countby
Gibt eine Zeile zurück, die alle durch den Ausdruck gruppierten Zeilen zählt.
countby <expression> [as <alias>] [into <keypath>]
Ein Alias kann angegeben werden, um den Tastaturpfad, in den das Ergebnis geschrieben wird, zu überschreiben.
Zum Beispiel der folgende Teil einer Abfrage
countby $d.verb into $d.verb_count
Das Ergebnis ist eine Zeile für jede Gruppe.
Sie ist funktionell identisch mit
groupby $data.verb calculate count() as $d.verb_count
create
Erstellen Sie einen neuen Schlüssel und setzen Sie seinen Wert auf das Ergebnis des Ausdrucks. Die Schlüsselerstellung ist granular, d. h. übergeordnete Schlüssel im Pfad werden nicht überschrieben.
(a|add|c|create) <keypath> from <expression> [on keypath exists (fail|skip|overwrite)] [on keypath missing (fail|create|skip)] [on datatype change (skip|fail|overwrite)
Die Erstellung kann durch Hinzufügen der folgenden Klauseln kontrolliert werden:
-
Durch Hinzufügen von
keypath existskönnen Sie festlegen, was geschehen soll, wenn der Tastaturpfad bereits existiert.-
overwrite- Überschreibt den alten Wert. Dies ist der Standardwert. -
fail- Die Abfrage schlägt fehl -
skip- Überspringt die Erstellung des Schlüssels
-
-
Das Hinzufügen von
keypath missingentscheidet, was zu tun ist, wenn der neue Tastaturpfad nicht existiert.-
create- Erzeugt den Schlüssel. Dies ist der Standardwert. -
fail- Die Abfrage schlägt fehl -
skip- Überspringt die Erstellung des neuen Schlüssels
-
-
Das Hinzufügen auf
datatype changedentscheidet, was zu tun ist, wenn der Schlüssel bereits existiert und die neuen Daten den Datentyp des Wertes ändern.-
overwrite- Überschreibt den Wert. Dies ist der Standardwert. -
fail- Die Abfrage schlägt fehl -
skip- Belässt den Schlüssel mit dem ursprünglichen Wert (und Typ)
-
Beispiele:
create $d.radius from 100+23
c $d.log_data.truncated_message from $d.message.substring(1,50)
c $data.trimmed_name from $data.username.trim()
create $d.temperature from 100*23 on datatype changed skip
distinct
Gibt eine Zeile für jede eindeutige Kombination der angegebenen Ausdrücke zurück.
distinct <expression> [as <alias>] [, <expression_2> [as <alias_2>], ...]
Dieser Operator ist funktional identisch mit groupby ohne Aggregatfunktionen.
enrich
Reichern Sie Ihre Protokolle mit zusätzlichem Kontext aus einer Nachschlagetabelle an.
Laden Sie Ihre Lookup-Tabelle mit Datenfluss > Data Enrichment > Custom Enrichment hoch.
enrich <value_to_lookup> into <enriched_key> using <lookup_table>
-
value_to_lookup- Ein String-Ausdruck, der in der Lookup-Tabelle nachgeschlagen wird. -
enriched_key- Zielschlüssel zur Speicherung des Anreicherungsergebnisses. -
lookup_table- Der Name der zu verwendenden Tabelle für die benutzerdefinierte Anreicherung.
Die Spalten der Tabelle werden als Unterschlüssel zum Zielschlüssel hinzugefügt. Wenn value_to_lookup nicht gefunden wird, ist der Zielschlüssel Null. Sie können dann die Ergebnisse mit den Funktionen von DataPrime filtern, z. B.
die Protokolle nach einem bestimmten Wert im angereicherten Feld.
Beispiel:
Das Originalprotokoll:
{
"userid": "111",
...
}
Die Nachschlagetabelle für benutzerdefinierte Anreicherungen heißt my_users:
| ID | Name | Abteilung |
|---|---|---|
| 111 | John | Finanzen |
| 222 | Emily | optimieren |
Ausführen der folgenden Abfrage:
enrich $d.userid into $d.user_enriched using my_users
Das Ergebnis ist das folgende angereicherte Protokoll:
{
"userid": "111",
"user_enriched": {
"ID": "111",
"Name": "John",
"Department": "Finance"
},
...
}
Beachten Sie bei der Verwendung von enrich die folgenden Punkte:
-
Führen Sie die DataPrime Abfragequelle
lookup_tableaus, um die Anreicherungstabelle anzuzeigen. -
Wenn das ursprüngliche Protokoll bereits den angereicherten Schlüssel enthält:
-
Wenn
value_to_lookupinlookup_tablevorhanden ist, werden die Unterschlüssel mit dem neuen Wert aktualisiert. Wenn dievalue_to_lookupnicht existiert, bleibt ihr aktueller Wert erhalten. -
Alle anderen Unterschlüssel, die keine Spalten in der
lookup_tablesind, bleiben mit ihren bestehenden Werten erhalten.
-
-
Alle Werte auf der Website
lookup_tablewerden als Zeichenketten betrachtet. Dies bedeutet Folgendes:-
Die Adresse
value_to_lookupmuss in einem String-Format vorliegen. -
Alle Werte werden in einem String-Format angereichert. Sie können sie dann mit den entsprechenden Funktionen in Ihr bevorzugtes Format (z. B. JSON, Zeitstempel) umwandeln.
-
extract
Extrahieren von Daten aus einem String-Wert in ein neues Objekt. Es werden mehrere Extraktionsmethoden unterstützt.
(e|extract) <expression> into <keypath> using <extraction-type>(<extraction-params>) [datatypes keypath:datatype,keypath:datatype,...]
Im Folgenden werden die unterstützten Extraktionsmethoden und ihre Parameter aufgeführt:
-
regexp- Ein neues Objekt auf der Grundlage von regexp capture-groups erstellen -
e- Ein regulärer Ausdruck mit Namen capture-groups.
Beispiel:
extract $d.my_text into $d.my_data using regexp(e=/user (?<user>.*) has logged in/)
-
kv- Extrahieren eines neuen Objekts aus einer Zeichenkette, die Schlüssel=Wert-Schlüssel=Wert-Paare enthält -
pair_delimiter- Das Trennzeichen, das zwischen Paaren erwartet wird. Standard ist (ein Leerzeichen) -
key_delimiter- Das zu erwartende Trennzeichen zwischen einem Schlüssel und einem Wert. Die Voreinstellung ist =.
Beispiele:
extract $d.text into $d.my_kvs using kv()
e $d.text into $d.my_kvs using kv(pair_delimiter=' ',key_delimiter='=')
-
jsonobject- Extrahieren eines neuen Objekts aus einem String, der ein kodiertes json-Objekt enthält, wobei möglicherweise versucht wird, den String zu entschlüsseln, bevor er in ein json-Objekt dekodiert wird -
max_unescape_count- Maximale Anzahl der Escape-Ebenen, die vor dem Parsen des json unescape sind. Der Standardwert ist '1'. Bei einem Wert von 1 oder mehr erkennt die Engine, ob der Wert eine escapte JSON-Zeichenfolge enthält, und entschlüsselt sie, bis die Anzahl der parsbaren oder maximalen Entschlüsselungen überschritten wird.
Beispiel:
e $d.json_message_as_str into $d.json_message using jsonobject(max_unescape_count=1)
Es ist möglich, Datentypinformationen als Teil der Extraktion bereitzustellen, indem die Datentypen-Klausel verwendet wird. Das Hinzufügen von Datentypen my_field:number zu einer Extraktion würde zum Beispiel dazu führen, dass der
Extrakt my_field keypath eine Zahl statt einer Zeichenkette ist. Zum Beispiel:
extract $d.my_msg into $d.data using kv() datatypes my_field:number
Die extrahierten Daten werden immer als Objekt in einen neuen Keypath eingefügt, so dass die neuen Schlüssel innerhalb dieses neuen Objekts weiterverarbeitet werden können. Zum Beispiel:
# Assuming a dataset which look like that:
{ "msg": "query_type=fetch query_id=100 query_results_duration_ms=232" }
{ "msg": "query_type=fetch query_id=200 query_results_duration_ms=1001" }
# And the following DataPrime query:
source logs
| extract $d.msg into $d.query_data using kv() datatypes
query_results_duration_ms:number
| filter $d.query_data.query_results_duration_ms > 500
# The results will contain only the second message, in which the duration is greater than 500 ms
filter
Ereignisse filtern, so dass nur Ereignisse übrig bleiben, für die die Bedingung als wahr ausgewertet wird.
(f|filter|where) <condition-expression>
Beispiele:
f $d.radius > 10
filter $m.severity.toUpperCase() == 'INFO'
filter $l.applicationname == 'myapp'
filter $l.applicationname == 'myapp' && $d.msg.contains('failure')
Der Vergleich mit null funktioniert nur für skalare Werte und gibt bei JSON-Teilbäumen immer null zurück.
Wenn Sie eine Bedingung verwenden, um einen Keypath mit Null zu vergleichen, funktioniert dies nur bei skalaren Werten (String, Zahl, Zeitstempel usw.). Bei JSON-Objekten innerhalb eines bestimmten Dokuments gibt der Vergleich mit null immer null zurück.
Verwenden Sie Filter mit Funktionen, um komplexe Suchen durchzuführen.
Beispiele:
filter in($l.applicationname, 'ibm-audit-event', 'ibm-platform-logs') #
filter ipInSubnet(ip_address, '155.64.5.20/24')
e - Filter für IP-Adressen in einem bestimmten Bereich. filter kann mit Funktionen gekoppelt werden, um komplexe Suchen mit sehr wenig Syntax durchzuführen, zum Beispiel mit der Funktion ipInSubnet:
filter ipInSubnet(ip_address, ' 154.67.8.20/24 ')
groupby
Gruppiert die Ergebnisse der vorangegangenen Operatoren nach den angegebenen Gruppierungsausdrücken und berechnet Aggregatfunktionen für jede erstellte Gruppe.
groupby <grouping_expression> [as <alias>] [, <grouping_expression_2> [as <alias_2>], ...] [calculate]
<aggregate_function> [as <result_keypath>]
[, <aggregate_function_2> [as <result_keypath_2], ...]
Beispielsweise sollte die Abfrage
groupby $m.severity calculate sum($d.duration)
Führt zu Protokollen der folgenden Form:
{ "severity": "Warning", "_sum": 17045 }
Die Tastaturpfade für die Gruppierungsausdrücke werden immer unter $d zu finden sein. Mit dem Schlüsselwort as können wir den Tastaturpfad für die Gruppierungsausdrücke und Aggregationsfunktionen umbenennen. Zum Beispiel:
groupby $l.applicationname as $d.app calculate sum($d.duration) as $d.sum_duration
Führt zu Protokollen der folgenden Form:
{ "app": "web-api", "sum_duration": 17045 }
Bei der Abfrage mit dem Operator groupby können Sie eine Aggregationsfunktion (z. B. avg, max, sum) auf den Bereich
der Ergebnisse anwenden. Diese Funktion gibt Ihnen die Möglichkeit, einen Aggregationsausdruck innerhalb des Ausdrucks selbst zu manipulieren, so dass Sie Ihre Daten gleichzeitig berechnen und manipulieren können.
join
Join führt die Ergebnisse der aktuellen (linken) Abfrage mit einer zweiten (rechten) Abfrage auf der Grundlage einer angegebenen Bedingung zusammen. Sie bietet mehrere Formulare, um zu steuern, wie die Daten kombiniert werden, und
unterstützt Verschachtelungen, so dass die richtige Abfrage ihren eigenen Befehl join enthalten kann.
Join unterstützt drei Varianten:
join left|join- Für jedes Ereignis in der linken Abfrage wählt der Befehl ein passendes Ereignis aus der rechten Abfrage auf der Grundlage der angegebenen Bedingung aus. Wenn keine Übereinstimmung gefunden wird, werden Zeilen für alle Ereignisse in der linken
Abfrage aufgenommen. Nicht übereinstimmende Zeilen aus der rechten Abfrage werden auf
nullgesetzt. join full- Gibt eine Zeile für jedes Ereignis zurück, einschließlich derer, für die es in beiden Abfragen (links oder rechts) keine Übereinstimmung gibt, wobei fehlende Werte mit
nullaufgefüllt werden. join inner- Gibt nur Zeilen zurück, in denen die Ergebnisse beider Abfragen nicht null sind.
join cross- Paart jede Zeile aus der linken Abfrage mit jeder Zeile aus der rechten Abfrage und erzeugt so das vollständige kartesische Produkt. Im Gegensatz zu anderen
joinTypen unterstütztjoin crossnichtonoderusing conditions. Sie funktioniert ähnlich wiejoin inner, allerdings ohne Filterung, und liefert alle möglichen Zeilenkombinationen.
Für left (Standard), inner und full können Sie entweder eine Bedingung join mit dem Schlüsselwort on oder einen Schlüsselpfad mit dem Schlüsselwort keyword angeben.
Das kartesische Produkt wird gefiltert, um nur Zeilen zu erhalten, bei denen die Bedingung zutrifft oder bei denen die Werte des Schlüsselpfads auf beiden Seiten übereinstimmen.
Da alle Verknüpfungen, unabhängig vom Modifikator, auf dem kartesischen Produkt basieren, kann es zu doppelten Ergebnissen kommen, wenn die Bedingung join mehrfach zutrifft. Um unbeabsichtigte Duplikationen zu vermeiden, sollten
Sie Unterabfragen vorverarbeiten, z. B. durch Verwendung von distinct.
Syntax:
<left_side_query> | join [left/inner/full] (<right_side_query>) on <condition> into <right_side_target>
<left_side_query> | join [left/inner/full] (<right_side_query>) using <join_keypath_1> [, <join_keypath_2>, ...] into <right_side_target>
<left_side_query> | join cross (<right_side_query>) into <right_side_target>
Dabei gilt:
-
<right_side_query>- Die<right_side_query>bezeichnet die neue Abfrage, mit der sie verbunden werden soll. -
<left_side_query>- Das<left_side_query>bezeichnet die ursprüngliche Abfrage, z.B. in der Abfragesource logs | filter x != null | join ...ist die linke Seite der Abfragesource logs | filter x != null. -
<condition>- Die Bedingung, ob Ergebnisse aus beiden Abfragen zusammengeführt werden sollen.In der Bedingung können Sie die Präfixe
left=>undright=>verwenden, um auf die Ereignisse der linken bzw. rechten Abfrage zu verweisen. Sie ist jedoch nicht erforderlich, wenn ein Schlüsselpfad nur in einer der Abfragen vorhanden ist.Wenn Sie den
==(Gleichheits-)Operator in Ihrer Bedingung verwenden, muss er einen Schlüsselpfad aus der linken Abfrage mit einem Schlüsselpfad aus der rechten Abfrage vergleichen. Da die Schlüsselpfade jedoch eindeutig sein müssen oder mitleft=>oderright=>vorangestellt werden, ist die Reihenfolge der Operanden nicht wichtig. -
<join_keypath_n>-<join_keypath_n>als Verknüpfungsschlüssel bedeutet, dass Ergebnisse verknüpft werden, bei denen ein bestimmter Schlüsselpfad sowohl in den Ergebnissen der linken als auch in denen der rechten Abfrage gleich ist. -
<right_side_target>- Der Schlüsselpfad, unter dem die verbundenen Daten zur aktuellen Abfrage hinzugefügt werden.
join Beispiel
Sie haben diese benutzerdefinierte Anreicherungstabelle mit dem Namen users, die Informationen über IDs in Verbindung mit Namen enthält:
{ "id": "111", "name": "John" }
{ "id": "222", "name": "Emily" }
{ "id": "333", "name": "Alice" }
Und diese Daten liefern Anmeldeereignisse und Benutzerkennungen, aber nicht die mit den Benutzerkennungen verbundenen Benutzernamen.
{ "userid": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "userid": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z" }
Mit join können Sie eine Abfrage verwenden, um Daten einschließlich der gewünschten Daten zurückzugeben.
source users | join (source logs | countby userid) on id == userid into logins
Diese Abfrage wird wie folgt bearbeitet:
-
Die
sourceist die benutzerdefinierte Anreicherungstabelle (users). -
Im
joinwird eine Zählung über das Felduseridvorgenommen. Daraus ergibt sich unsere Statistikcount. -
Das Feld
idin der benutzerdefinierten Anreicherungstabelle wird mit dem Felduseridin den Protokollen verglichen. -
Das Ergebnis wird auf die Taste
loginsübertragen. Wenn der Schlüsselloginsbereits in der linken Abfrage vorhanden ist, wird er überschrieben.
Zum Beispiel:
{ "id": "111", "name": "John", "logins": { "userid": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "userid": "222", "_count": 3 } }
{ "id": "333", "name": "Alice", "logins": null }
Das Ergebnis der Abfrage auf der rechten Seite befindet sich nun im Feld logins. Beachten Sie, dass es keine Anmeldungen für die Benutzer-ID 333 (Alice) gab, so dass das Feld Anmeldungen null lautet,
weil es kein Ergebnis gab, das mit der Bedingung join übereinstimmte.
join beispiel mit dem Schlüsselwort using
Nehmen wir an, unser Login-Datensatz ist:
{ "id": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
In diesem Fall enthalten die Daten auf beiden Seiten der Verknüpfung das Feld id. In diesem Fall kann das Schlüsselwort using verwendet werden, um die gemeinsamen Daten zu nutzen:
source users | join (source logins | countby id) using id into logins
Das Ergebnis ist ähnlich, aber anstelle von userid wird das Feld id zurückgegeben.
{ "id": "111", "name": "John", "logins": { "id": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "_count": 3 } }
{ "id": "333", "name": "Alice", "logins": null }
Wenn Sie zwei Felder haben, die unterschiedlich benannt sind, aber Ihre join Abfrage vereinfachen würden, können Sie mit move verwenden,
um eines der Felder zu verschieben, damit die Schlüsselpfade auf beiden Seiten übereinstimmen.
join beispiel mit den Schlüsselwörtern left=> und right=>
Sie können die Präfixe left=> und right=> verwenden, um auf die Ereignisse der linken und rechten Abfrage zu verweisen. Sie ist jedoch nicht erforderlich, wenn ein Schlüsselpfad nur in einer der Abfragen vorhanden
ist.
Betrachten Sie die Daten aus dem vorangegangenen Beispiel und stellen Sie sich folgende Frage:
source users | join (source logins | countby id) on left=>id == right=>id into logins
Dies ist erforderlich, weil beide Datensätze ein Feld mit demselben Namen enthalten (id). Damit DataPrime ein Feld eindeutig identifizieren kann, muss es wissen, auf welche Seite der Abfrage wir uns beziehen. Diese Abfrage ergibt
die gleiche Ausgabe wie die vorherige, bei der das Schlüsselwort using verwendet wurde.
Wenn Sie den == (Gleichheits-)Operator in Ihrer Bedingung verwenden, muss er einen Schlüsselpfad aus der linken Abfrage mit einem Schlüsselpfad aus der rechten Abfrage vergleichen. Da die Schlüsselpfade jedoch eindeutig sein müssen
oder mit left=> oder right=> vorangestellt werden, ist die Reihenfolge der Operanden nicht wichtig.
join full Beispiel
Sie haben diese benutzerdefinierte Anreicherungstabelle mit dem Namen users, die Informationen über IDs in Verbindung mit Namen enthält:
{ "id": "111", "name": "John" }
{ "id": "222", "name": "Emily" }
{ "id": "333", "name": "Alice" }
Und betrachten Sie diesen Datensatz:
{ "id": "001", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
Die zweite Gruppe von Dokumenten (rechte Abfrage) enthält einen Protokolleintrag mit "id": "001", der in der ersten Gruppe von Dokumenten (linke Abfrage) nicht vorhanden ist. Wenn Sie einen Standard-Join verwenden,
wird dieser Eintrag aus der rechten Abfrage ignoriert und erscheint nicht im Ergebnis. Um sicherzustellen, dass jedes id Feld in der Ausgabe enthalten ist, unabhängig davon, ob es in der linken oder rechten Abfrage erscheint,
können Sie join full verwenden:
source users | join full (source logins | countby id) using id into logins
Diese Abfrage führt zu folgenden Ergebnissen:
{ "id": "001", "name": "null", "logins": { "id": "001", "_count": 1 } }
{ "id": "111", "name": "John", "logins": { "id": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "_count": 3 } }
{ "id": "333", "name": "Alice", "logins": null }
Durch die Verwendung von join full bleiben alle id Felder aus beiden Datensätzen erhalten, und alle fehlenden Werte werden auf null gesetzt.
join full ist besonders nützlich, wenn die Ergebnisse beider Abfragen Zeitspannen enthalten. Wenn beispielsweise in den Ergebnissen der linken Abfrage ein Zeitbereich für eine bestimmte Stunde fehlt (z. B. XX:XX:XX),
wird dieser Datenpunkt mit join full aufgenommen. Dies ist besonders nützlich für den Vergleich zweier Zeitreihen in einem Diagramm.
join inner Beispiel
Wenn Sie alle Zeilen entfernen möchten, wenn Spaltenergebnisse für die linken oder rechten Abfragen einen Nullwert ergeben, verwenden Sie join inner.
Anhand der vorherigen Daten werden bei dieser Abfrage Zeilen mit nicht übereinstimmenden Daten auf beiden Seiten entfernt:
source users | join inner (source logins | countby id) using id into logins
-
Die linke Abfrage
source usersruft den Benutzerdatensatz ab, der die Felderidundnameenthält. -
Die rechte Abfrage (
source logins | countby id) ruft den Logins-Datensatz ab, gruppiert nachidund zählt die Vorkommen für jedesid. -
join innergleicht Zeilen ab, in denenidin beiden Datensätzen vorhanden ist, und führt die Daten zu einem einzigen Datensatz zusammen. -
Zeilen, die in keinem der beiden Datensätze übereinstimmen, werden von den endgültigen Ergebnissen ausgeschlossen.
In diesem Fall ergeben sich für die beiden oben genannten Dokumentensätze die folgenden Ergebnisse:
{ "id": "111", "name": "John", "logins": { "id": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "_count": 3 } }
join cross Beispiel
join cross kombiniert jede Zeile aus der linken Abfrage mit jeder Zeile aus der rechten Abfrage und erzeugt ein kartesisches Produkt der beiden Mengen.
Angenommen, wir haben die folgenden Dokumente aus einer benutzerdefinierten Anreicherungstabelle namens users.
{ "id": "111", "name": "John" }
{ "id": "222", "name": "Emily" }
{ "id": "333", "name": "Alice" }
Betrachten Sie nun diese Menge von Dokumenten mit dem Namen logs.
{ "id": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
Die folgende Abfrage erzeugt ein kartesisches Produkt aus den Datensätzen users und logs, da join cross jede Zeile aus der linken Abfrage mit jeder Zeile aus der rechten Abfrage paart, unabhängig von
übereinstimmenden Bedingungen.
source users | join cross (source logs) into logins
{ "id": "111", "name": "John", "logins": { "id": "111", "timestamp": "2022-01-01T12:00:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "111", "timestamp": "2022-01-01T12:30:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "111", "timestamp": "2022-01-01T12:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "111", "timestamp": "2022-01-01T12:30:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "111", "timestamp": "2022-01-01T12:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "111", "timestamp": "2022-01-01T12:30:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
Die Abfrage führt dazu, dass jeder Benutzer mit jedem Protokolleintrag gepaart wird: 3 Zeilen aus users multipliziert mit 5 Zeilen aus logs, was 15 Zeilen ergibt. Jeder Benutzer (John, Emily,
Alice) ist mit jedem Protokolleintrag gepaart.
Die Verwendung von join cross ist vor allem dann sinnvoll, wenn Sie sich ein vollständiges Bild von Ihren Daten machen möchten und dann zu diesen Ergebnissen eine left oder right join hinzufügen
möchten.
Beschränkungen und Überlegungen
Es gibt Einschränkungen und Überlegungen bei der Einbeziehung von join in eine Abfrage:
-
Die Bedingung
joinunterstützt nur die Gleichheit von Schlüsselpfaden (==). Wenn mehrere Gleichheitsbedingungen benötigt werden, können sie mit&&(logisch und) kombiniert werden. -
Eine Seite der Verknüpfung (entweder aktuelle Abfrage oder Verknüpfungsabfrage) muss klein sein (< 200MB ). Sie können verwenden
filterundremoveverwenden, um die Größe der Abfrage zu verringern. -
Bei Left Outer Joins müssen alle Spalten in der Bedingung ungleich Null sein. Alle Nullspalten werden nicht verbunden. Um Nullspalten der rechten Abfrage einzuschließen, verwenden Sie
join full. Um alle Nullspalten auszuschließen, die von den linken und rechten Joins erzeugt werden, verwenden Siejoin inner.
limit
Begrenzt die Ausgabe auf die ersten event-count Ereignisse.
limit <event-count>
Beispiel:
limit 100
move
Verschieben eines Schlüssels (einschließlich seiner Unterschlüssel, falls vorhanden) an eine neue Position.
(m|move) <source-keypath> to <target-keypath>
Beispiele:
move $d.my_data.hostname to $d.my_new_data.host
m $d.kubernetes.labels to $d.my_labels
multigroupby
multigroupby fasst die Ergebnisse von zwei oder mehr Abfragen unter Einbeziehung von groupby zu einem einzigen Datensatz zusammen.
Verwenden Sie multigroupby für:
-
Effizient: Die Daten werden bei Mehrfachabfragen nur einmal gescannt.
-
Synchronisierung: Die Ergebnisse bleiben kohärent, so dass Diskrepanzen vermieden werden, die bei der Ausführung getrennter Abfragen entstehen können.
multigroupby (<grouping_expression_1> as <alias> [, <grouping_expression_2> as <alias_2>, ...]) [, (<grouping_expression_1> as <alias> [, <grouping_expression_2> as <alias_2>, ...]), ...][calculate] <aggregation_expression> [as <result_keypath>] [, <aggregation_expression_2> [as <result_keypath_2], ...]
Durch die Verwendung desselben Alias app für beide Gruppierungen wird die gleiche semantische Bedeutung als ein einheitliches Feld dargestellt. Im nächsten Beispiel werden verschiedene Aliasnamen verwendet und die Daten kombiniert,
aber nicht zusammengeführt.
Beispiel - Multigroupby mit demselben Alias
In diesem Beispiel wollen wir unsere Protokolle wie folgt gruppieren:
-
Zunächst nach
applicationname(app) und dann weiter nachsubsystemname(ss), mit detaillierten Zählungen für jede Kombination. -
Dann unabhängig von
applicationname, was die Gesamtzahl der Protokolle für jede Anwendung unabhängig vonsubsystemsergibt.
source logs
| multigroupby ($l.applicationname as app, $l.subsystemname as ss),($l.applicationname as app) calculate count() | orderby app,ss
Das Ergebnis wird ähnlich sein:
[
{
"_count0": 241,
"app": "monitoring24",
"ss": "NO_SUBSYSTEM_NAME"
},
{
"_count0": 231,
"app": "monitoring24",
"ss": "logs-opentelemetry-agent"
},
{
"_count0": 15,
"app": "monitoring24",
"ss": "logs-opentelemetry-collector"
},
{
"_count0": 487,
"app": "monitoring24",
"ss": null
}
]
Die ersten drei Zeilen stellen die Zählungen für jede eindeutige Kombination von app und ss dar. Zum Beispiel gibt es 241 Protokolle, bei denen die Anwendung (app) monitoring24 und das Subsystem
(ss) NO_SUBSYSTEM_NAME ist. In ähnlicher Weise gibt es 231 Protokolle für dieselbe Anwendung, aber mit dem Subsystem logs-opentelemetry-agent und so weiter.
In der letzten Zeile wird die Gesamtzahl der Protokolle für die Anwendung monitoring24 angegeben, wobei alle Teilsysteme zusammengefasst werden. Hier beträgt _count0 487, die Summe aller oben genannten detaillierten
Zählungen. Das Feld ss ist null, um anzugeben, dass es sich um die Gesamtsumme für den gesamten Antrag handelt.
Durch die Verwendung desselben Alias app für beide Gruppierungen wird die gleiche semantische Bedeutung als ein einheitliches Feld dargestellt. Im nächsten Beispiel werden verschiedene Aliasnamen verwendet und die Daten kombiniert,
aber nicht zusammengeführt.
Beispiel - Multigroupby mit verschiedenen Aliasnamen
Betrachten wir nun die Auswirkungen der Einführung von 2 verschiedenen Aliasen für die Abfragen. In diesem Fall wird die erste Gruppierung als app1 für applicationname kombiniert mit ss bezeichnet, während
die zweite Gruppierung als app2 für applicationname alone bezeichnet wird.
source logs | multigroupby ($l.applicationname as app1, $l.subsystemname as ss),($l.applicationname as app2) calculate count()
Das Ergebnis wird ähnlich sein:
[
{
"_count0": 241,
"app1": "monitoring24",
"app2": null,
"ss": "logs-opentelemetry-agent"
},
{
"_count0": 231,
"app1": "monitoring24",
"app2": null,
"ss": "logs-opentelemetry-collector"
},
{
"_count0": 15,
"app1": "monitoring24",
"app2": null,
"ss": "no_subsystem_name"
},
{
"_count0": 487,
"app1": null,
"app2": "monitoring24",
"ss": null
}
]
Durch die Einführung separater Aliasnamen (app1 und app2) behält die Abfrage die Unterscheidung zwischen den beiden Gruppierungen bei, anstatt die Daten zusammenzuführen. Zeilen, in denen app1 ausgefüllt
ist und app2 null ist, entsprechen der detaillierten Gruppierung nach applicationname und subsystemname. Zum Beispiel sind 241 Protokolle mit app1 = "monitoring24" und ss = "logs-opentelemetry-agent" verbunden. Dies entspricht der ersten Gruppierungslogik.
Die Zeile, in der app2 aufgefüllt wird und app1 null ist, spiegelt die Gesamtzahl für die zweite Gruppierung wider, bei der die Protokolle ausschließlich nach applicationname aggregiert werden.
Für app2 = "monitoring24" beträgt die Anzahl 487, und sowohl app1 als auch ss sind null, um diese übergeordnete Aggregation anzuzeigen.
Durch die Verwendung separater Aliasnamen (app1 und app2) führt die Abfrage die Daten nicht zusammen, sondern macht deutlich, zu welcher Gruppe die einzelnen Ergebnisse gehören. Die allgemeine Logik bleibt dieselbe:
detaillierte Zählungen für spezifische Kombinationen und aggregierte Zählungen für die Gesamtzahl.
Multigroupby - Einschränkungen
multigroupby gibt keine doppelten Zeilen für doppelte Gruppensätze zurück.
Wenn Sie multigroupby mit app und ss ausführen, könnte das erwartete Ergebnis (wenn Duplikate zulässig wären) wie folgt aussehen:
[
{"app": "monitoring24", "ss": "logs-opentelemetry-agent", "_count0": 2},
{"app": "monitoring24", "ss": "logs-opentelemetry-collector", "_count0": 2}
]
Aufgrund dieser Einschränkung führt multigroupby diese Duplikate zusammen und gibt nur eine Zeile für jede eindeutige Kombination zurück, auch wenn diese Kombination mehrfach in den Daten vorkommt:
[
{"app": "monitoring24", "ss": "logs-opentelemetry-agent", "_count0": 2}
]
orderby / sortby / order by / sort by
Sortieren Sie die Daten in aufsteigender/absteigender Reihenfolge nach dem Wert des Ausdrucks. Das Ordnen nach mehreren Ausdrücken wird unterstützt.
(orderby|sortby|order by|sort by) <expression> [(asc|desc)] , ...
Beispiele:
orderby $d.myfield.myfield
orderby $d.myfield.myfield:number desc
sortby $d.myfield desc
Die Sortierung numerischer Werte kann durch Casting des Ausdrucks auf den Typ: erfolgen, z. B. <expression>: number. In einigen Fällen wird dies von der Maschine automatisch abgeleitet.
redact
Ersetzt alle Teilzeichenketten, die mit einem Regexp-Muster übereinstimmen, aus einem Keypath-Wert und verbirgt so den ursprünglichen Inhalt.
Das passende Schlüsselwort ist optional und kann zur Verbesserung der Lesbarkeit verwendet werden.
redact <keypath> [matching] /<regular-expression>/ to '<redacted_str>'
redact <keypath> [matching] <string> to '<redacted_str>'
Beispiele:
redact $d.mykey /[0-9]+/ to 'SOME_INTEGER'
redact $d.mysuperkey.user_id 'root' to 'UNKNOWN_USER'
redact $d.mysuperkey.user_id matching 'root' to 'UNKNOWN_USER'
remove
Entfernt einen Tastaturpfad aus dem Objekt.
r|remove <keypath1> [ "," <keypath2> ]...
Beispiele:
r $d.mydata.unneeded_key
remove $d.mysuperkey.service_name, $d.mysuperkey.unneeded_key
replace
Ersetzen Sie den Wert eines Schlüssels durch einen neuen Wert.
Wenn der Ersetzungswert den Datentyp des Keypaths ändert, stehen die folgenden Optionen zur Verfügung:
-
skip- Die Ersetzung wird ignoriert -
fail- Die Abfrage wird fehlschlagen -
overwrite- Der neue Wert überschreibt den vorherigen Wert und ändert den Datentyp des Keypaths
replace <keypath> with <expression> [on datatype changed skip/fail/overwrite]
Beispiele:
replace $d.message with null
replace $d.some_superkey.log_length_plus_10 with $d.original_log.length()+10 on datatype changed overwrite
roundtime
Rundet die Zeit des Ereignisses in ein bestimmtes Zeitintervall und erstellt möglicherweise einen neuen Schlüssel für das Ergebnis.
-
Wenn
source-timestampnicht angegeben wird, wird$m.timestampals Quellzeitstempel verwendet. -
Wenn
source-timestampangegeben wird, sollte es vom Typtimestampsein (oder in diesen umgewandelt werden).
Standardmäßig wird das gerundete Ergebnis in den Quell-Keypath source-timestamp zurückgeschrieben. Wenn in target-keypath angegeben wird, wird source-timestamp nicht geändert und das Ergebnis wird in ein
neues target-keypath geschrieben.
Unterstützte Zeitintervalle sind:
- Xns - X Nanosekunden (Achten Sie auf die Auflösung des Zeitstempels der Quelle)
- Xms - X Millisekunden
- Xs - X Sekunden
- Xm - X Minuten
- Xh - X Stunden
- Xd - X Tage
Und jede Kombination von größeren zu kleineren Zeiteinheiten, zum Beispiel 1h30m15s.
roundtime [source-timestamp] to <time-interval> [into <target-keypath>]
Beispiele:
roundtime to 1h into $d.tm
roundtime $d.timestamp to 1h
roundtime $d.my_timestamp: timestamp to 60m
roundtime to 60s into $d.rounded_ts_to_the_minute
source
Legen Sie die Datenquelle fest, auf der Ihre DataPrime-Abfrage basiert.
(source|from) <data_store>
Wobei data_store entweder sein kann:
-
logs -
Der Name der benutzerdefinierten Anreicherung. In diesem Fall wird der Befehl die benutzerdefinierte Anreicherungstabelle anzeigen.
Beispiele:
source logs
stitch
Der Befehl stitch führt eine horizontale Vereinigung von zwei Datensätzen durch, indem er sie Seite an Seite kombiniert. Es gleicht Zeilen aus einem Datensatz mit Zeilen aus einem anderen ab und verkettet ihre Spalten, wodurch ein
einziger, einheitlicher Datensatz entsteht.
Bei Verwendung des Befehls stitch:
-
Die Datensätze müssen geordnet sein, da die Zeilen der Reihe nach kombiniert werden (d. h. Zeile 1 von Datensatz A wird mit Zeile 1 von Datensatz B zusammengefügt).
-
Wenn ein Datensatz mehr Zeilen als der andere hat, haben nicht übereinstimmende Zeilen Nullwerte in den zusammengefügten Spalten.
-
Das resultierende Dataset enthält alle Spalten aus beiden Datasets.
stitch unterscheidet sich von union. stitch kombiniert Datensätze horizontal, indem es Spalten zeilenweise anhängt. union hängt Zeilen vertikal an, indem es Datensätze übereinander stapelt.
... | stitch (<subquery>) into <target-keypath>
Beispiel:
Sie haben diese benutzerdefinierten Anreicherungstabellen:
sales datensatz:
{ "product": "Widget", "sales": 100 }
{ "product": "Gadget", "sales": 200 }
{ "product": "Dashboard", "sales": 150 }
revenue datensatz:
{ "product": "Widget", "revenue": 5000 }
{ "product": "Gadget", "revenue": 8000 }
{ "product": "Dashboard", "revenue": 6000 }
In dieser Abfrage kombinieren Sie diese Datensätze nebeneinander und stellen sicher, dass jede Zeile des einen Datensatzes mit der entsprechenden Zeile des anderen Datensatzes übereinstimmt:
source sales | orderby product
| stitch (source revenue | orderby product) into combined_data
-
source salesholt alle Zeilen aus dem Datensatzsales, der Produkte und die entsprechenden Verkaufszahlen enthält. -
orderby productsortiert den Datensatzsalesnach dem Feldproduct, um eine einheitliche Reihenfolge für die Ausrichtung der Zeilen zu schaffen. -
stitch (source revenue | orderby product)holt Zeilen aus dem Datensatzrevenueund sortiert sie nach dem Feldproduct. Die Datensätzesalesundrevenuewerden horizontal kombiniert, wobei die Zeilen nach der Sortierung in ihrer Reihenfolge ausgerichtet werden. -
into combined_dataspeichert den kombinierten Datensatz in einer Variablen namenscombined_data.
Das Ergebnis der Abfrage ist:
{ "product": "Widget", "sales": 100, "combined_data": { "product": "Widget", "revenue": 5000 } }
{ "product": "Gadget", "sales": 200, "combined_data": { "product": "Gadget", "revenue": 8000 } }
{ "product": "Dashboard", "sales": 150, "combined_data": { "product": "Dashboard", "revenue": 6000 } }
Wenn die Datensätze ungleiche Zeilen haben, füllt der Befehl stitch die fehlenden Werte mit null auf.
Nehmen wir zum Beispiel die folgenden Datensätze:
sales datensatz (3 Zeilen):
{ "product": "Widget", "sales": 100 }
{ "product": "Gadget", "sales": 200 }
{ "product": "Dashboard", "sales": 150 }
revenue datensatz (2 Zeilen):
{ "product": "Widget", "revenue": 5000 }
{ "product": "Gadget", "revenue": 8000 }
Diese Abfrage wird ausgeführt:
source sales | orderby product
| stitch (source revenue | orderby product) into combined_data
Ergebnisse in:
{ "product": "Widget", "sales": 100, "combined_data": { "product": "Widget", "revenue": 5000 } }
{ "product": "Gadget", "sales": 200, "combined_data": { "product": "Gadget", "revenue": 8000 } }
{ "product": "Dashboard", "sales": 150, "combined_data": { "product": "Dashboard", "revenue": null } }
stitch Hinweise zur Verwendung
-
Die Zeilen müssen logisch zusammenhängen, damit das Heften sinnvolle Ergebnisse liefert. Vergewissern Sie sich, dass die Zeilen aus beiden Datensätzen dieselben Entitäten darstellen und in derselben Reihenfolge angeordnet sind. Wenn z. B. das Feld
productim Datensatzsalesnicht mit dem Feldproductim Datensatzrevenuefür die entsprechenden Zeilen übereinstimmt, funktioniert die Verknüpfung nicht wie erwartet. -
Wenn sich die Datensätze in der Zeilenzahl unterscheiden, enthält das Ergebnis
nullWerte für fehlende Daten in dem kürzeren Datensatz.
top
Keine Gruppierungsvariante: Begrenzt die zurückgegebenen Zeilen auf eine bestimmte Anzahl und ordnet das Ergebnis nach einer Reihe von Ausdrücken.
order_direction := "descending"/"ascending" according to top/bottom
top <limit> <result_expression1> [as <alias>] [, <result_expression2> [as <alias2>], ...] by <orderby_expression> [as alias>]
Beispielsweise sollte die Abfrage
top 5 $m.severity as $d.log_severity by $d.duration
Führt zu Protokollen der folgenden Form:
[
{ "log_severity": "Warning", "duration": 2000 },
{ "log_severity": "Debug", "duration": 1000 }
...
]
Gruppierungsvariation: Begrenzt die zurückgegebenen Zeilen auf eine bestimmte Anzahl und gruppiert sie nach einer Reihe von Aggregationsausdrücken und ordnet sie nach einer Reihe von Ausdrücken.
order_direction := "descending"/"ascending" according to top/bottom
top <limit> <(groupby_expression1|aggregate_function1)> [as <alias>] [, <(groupby_expression2|aggregate_function2)> [as <alias2>], ...] by <(groupby_expression1|aggregate_function1)> [as <alias>]
Beispielsweise sollte die Abfrage
top 10 $m.severity, count() as $d.number_of_severities by avg($d.duration) as $d.avg_duration
Führt zu Protokollen der folgenden Form:
[
{ "severity": "Debug", "number_of_severities": 10, avg_duration: 2000 }
{ "severity": "Warning", "number_of_severities": 50, avg_duration: 1000 },
...
]
Sie können eine Aggregationsfunktion anwenden..
union
Der Befehl union fasst die Ergebnisse von zwei oder mehr Datensätzen zu einem Datensatz zusammen. Dies ermöglicht es den Nutzern, die Ergebnisse mehrerer Abfragen in einem einzigen nahtlosen Datensatz zu kombinieren. Ein Datensatz
kann eine Ergebnismenge sein, die über die Pipeline in den Befehl union geleitet und dann mit einem anderen Datensatz verkettet wird.
Verwenden Sie union, wenn Sie Zeilen aus einem Datensatz an einen anderen anhängen müssen.
Um die Leistung bei der Verarbeitung großer Datensätze zu optimieren, sollten Sie die Verwendung von filter in Betracht ziehen, um Zeilen aus jedem Datensatz zu begrenzen, bevor Sie union verwenden.
Die Benutzer können maximal 10 union Befehle pro Abfrage für Prioritätserkenntnisse Daten verwenden. Für andere Daten gibt es keine Beschränkungen.
Wie unterscheidet sich union von join
-
unionkombiniert Ergebnismengen durch Anhängen von Zeilen aus einem Datensatz an einen anderen. Es werden keine Spalten aus mehreren Dokumenten zusammengeführt oder verglichen. -
joingleicht Spalten aus zwei Tabellen auf der Grundlage einer Bedingung ab und kombiniert sie, wodurch Zeilen entstehen, die Daten aus beiden Tabellen enthalten.
<query> | union <query>
Beispiel für die Kombination von 2 Datensätzen
Sie haben diese 2 Datensätze:
Protokolle für Team 58942
{ "id": "111", "name": "John" , "team.id": "58942" }
{ "id": "222", "name": "Emily", "team.id": "58942" }
{ "id": "333", "name": "Alice", "team.id": "58942" }
Protokolle für Team 98361
{ "userid": "111", "timestamp": "2022-01-01T12:00:00Z", "team.id": "98361" }
{ "userid": "111", "timestamp": "2022-01-01T12:30:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
Und Sie wollen sie zu einem Datensatz zusammenfassen. Sie können dies mit union tun.
source logs(teamId=58942) | union logs(teamId=98361)
Die Abfrage verarbeitet die beiden Datensätze:
source logs(teamId=58942): Ruft alle Dokumente ab fürTeam 58942union logs (teamID=98361): Hängt den DatensatzTeam 98361an den DatensatzTeam 58942an
Das Ergebnis ist der folgende Datensatz:
{ "id": "111", "name": "John" , "team.id": "58942" }
{ "id": "222", "name": "Emily", "team.id": "58942" }
{ "id": "333", "name": "Alice", "team.id": "58942" }
{ "userid": "111", "timestamp": "2022-01-01T12:00:00Z", "team.id": "98361" }
{ "userid": "111", "timestamp": "2022-01-01T12:30:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }