2016-03-29 18 views
5

Ich bin neu in BigQuery (und SQL) und versuche, eine Tabelle einzurichten, in der jede Zeile eine message Spalte (String) und metadata Spalte (wiederholt) enthält. Ich möchte die Metadatenspalte verwenden, um nach Nachrichten zu suchen, die bestimmten Metadatenparametern entsprechen.Abfrage BigQuery verschachtelte/wiederholte Felder

Zum Beispiel meine Nachrichtenkette ist:

Hi honey, I'm home!

und die Metadatenspalte ist beliebig Schlüssel/Wert-Paare, die die Nachricht beschreiben:

{"category": "personal", "message_type": "salutation"}

Dies würde erlauben Sie mir, frage bigquery an:

gib mir alle messages zurück ein category von personal (oder message_type von personal usw.)

Um es zu wiederholen, wird der Metadaten-Schlüssel für jede Nachricht potentiell Zeile unterschiedlich sein, die eingefügt wird (z.B. Eine neue Zeile kann einen Metadatenschlüssel von favorite_color anstelle von category haben).

Hier ist das Schema, das ich mit, um die Metadaten Flexibilität zu unterstützen kam, die ich wünsche:

[ 
{"name": "message", "type": "string", "mode": "required"} 
{"name": "metadata", "type": "record", "mode": "repeated", "fields": [ {"name": "key", 
                     "type": "string", 
                     "mode": "required"}, 
                     {"name": "value", 
                     "type": "string", 
                     "mode": "required"}]} 
] 

Das Schema erwartet, dass jede Eingabe von Metadaten/Zeile enthält eine Spalte mit dem Namen genannt key und Spalte value. Es scheint gut zu funktionieren. Interessanter

stellt BigQuery meine Nachricht Zeile als zwei Zeilen (was ich denke, ist „Abflachung“ genannt?):

message     | metadata_key | metadata_value 
------------------------------------------------------------ 
Hi honey, I'm home!  category    personal 
Hi honey, I'm home!  message_type   salutation 

ich herausgefunden, wie gegen einen einzelnen Metadatenwert abzufragen, wie category = personal:

SELECT * FROM [table.test] 
WHERE 
metadata.key="category" AND metadata.value="personal" 

ich eine einzelne Zeile zurück:

message     | metadata_key | metadata_value 
------------------------------------------------------------ 
Hi honey, I'm home!  category    personal 

Das ist großartig! Allerdings weiß ich nicht, wie eine komplexere Abfrage zu erstellen, die mehrere Metadaten-Parameter übereinstimmt gegen, wie zB:

Hol mir alle Nachrichten, die eine category von personal und message_type von salutation

Das folgende haben Abfrage gibt nichts zurück:

SELECT * FROM [table.test] 
WHERE 
metadata.key="category" AND metadata.value="personal" AND 
metadata.key="message_type" AND metadata.value="salutation" 

ich nehme an, das liegt daran, dass BigQuery zusammenbricht meine einzige Nachricht Zeile in zwei Reihen (einer für jede verschachtelte Metadaten Reihe). Das bedeutet natürlich, dass meine Abfrage niemals mit einer einzelnen Zeile übereinstimmen kann, weil ich versuche, zwei verschiedene Metadatenzeilen abzugleichen (dh ich möchte, dass metadata.key zwei verschiedenen Werten gleichzeitig entspricht, und Metadaten .Wert ist gleich verschiedenen Werten gleichzeitig). Daher bin ich etwas ratlos, wie ich meine Abfrage entsprechend aufbauen kann.

Idealerweise möchte ich, dass BigQuery eine Zeile zurückgibt (die ursprüngliche Beispielzeile, mit der ich angefangen habe), da sie die beiden Metadatenanforderungen meiner Abfrage erfüllt.

Ich nehme an, ich brauche eine Kombination von GROUP BY, FLATTEN, WITHIN, unflatten usw. Die Kombination von Möglichkeiten/Struktur ist für diesen sql/bigquery Anfänger etwas entmutigend. Jede Hilfe dankbar :)

Antwort

5

unten Versuchen - nur eine von Optionen
Es fasst, wie viele „entspricht, die Sie in jeder Zeile und wenn alle (in diesen Fällen - 2). Es gibt es recht einfach

SELECT *, 
SUM((metadata.key="category" AND metadata.value="personal") 
OR (metadata.key="message_type" AND metadata.value="salutation") 
) WITHIN RECORD AS check, 
FROM [table.test] 
HAVING check = 2 

Cleaner-Version davon wäre wie folgt

SELECT * 
FROM [table.test] 
OMIT RECORD IF 
SUM((metadata.key="category" AND metadata.value="personal") 
OR (metadata.key="message_type" AND metadata.value="salutation") 
) != 2  
Verwandte Themen