2016-03-29 16 views
5

Jestem nowym użytkownikiem BigQuery (i sql) i próbuję skonfigurować tabelę, w której każdy wiersz zawiera kolumnę message (ciąg) i metadata kolumnę (powtórzoną). Chcę użyć kolumny metadanych, aby móc wyszukiwać wiadomości pasujące do określonych parametrów metadanych.Zapytania BigQuery zagnieżdżone/powtórzone pola

Na przykład, moja wiadomość ciąg jest:

Hi honey, I'm home!

a kolumna metadane par klucz/wartość arbitralne opisujące wiadomość:

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

Pozwoliłoby mi się zapytać BigQuery do:

powrócić mi wszystkie wiadomości, które mają category z personal (lub message_type z personal, etc)

Powtarzając klawisze metadanych potencjalnie być różny dla każdej wiadomości rzędu włożonej (np nowy wiersz może mieć klucz metadanych o numerze favorite_color zamiast category).

Oto schemat, który wymyśliłem w celu wspierania elastyczności metadanych że pragnienie:

[ 
{"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"}]} 
] 

Schemat oczekuje, że każdy metadanych wejścia/wiersz zawiera kolumnę o nazwie key i kolumnę o nazwie value. Wygląda na to, że działa dobrze.

ciekawe, BigQuery reprezentuje moją wiadomość wiersz jako dwóch rzędach (co chyba jest nazywany „spłaszczenie”):

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

I zorientowali się, jak kwerendy przeciwko pojedynczej wartości metadanych, takich jak category = personal:

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

uzyskać pojedynczy wiersz z powrotem:

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

To jest świetne! Jednak nie wiem jak skonstruować bardziej złożone zapytania, który odpowiada przed wieloma parametrami metadanych, takich jak:

Przynieś mi wszystkie wiadomości, które mają category z personal i message_type z salutation

Ten poniższy kwerenda nie zwraca niczego:

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

Zakładam, to dlatego, że jest BigQuery uszkodzi mój pojedynczej wiadomości wiersz w dwóch rzędach (po jednym dla każdego zagnieżdżonego rzędu metadanych). To oczywiście oznacza, że ​​moje zapytanie nie będzie w stanie dopasować jeden wiersz, ponieważ staram się dopasować na dwóch różnych wierszy metadanych (tj pytam metadata.key być równa dwóch różnych wartości w tym samym czasie, a metadane .value równy różnym wartościom w tym samym czasie). Więc jestem nieco zakłopotany, jak poprawnie skonstruować moje zapytanie.

Idealnie chciałbym, aby BigQuery zwrócił pojedynczy wiersz (oryginalny przykładowy wiersz, od którego zacząłem), ponieważ spełnia on dwa wymagania dotyczące metadanych mojego zapytania.

Zakładam, że potrzebuję jakiejś kombinacji GROUP BY, FLATTEN, WITHIN, unflatten, itp. Połączenie możliwości/struktury jest nieco zniechęcające dla początkującego sql/bigquery. Każda pomoc mile widziane :)

Odpowiedz

5

Spróbuj poniżej - tylko jedną z opcji
To podsumowuje ile „pasuje masz w każdym rzędzie i jeśli wszystko (w tym przypadku - 2). Wyprowadza go Całkiem proste

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 

Czystsza wersja tego będzie poniżej

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