查询BigQuery嵌套/重复字段

时间:2016-03-29 23:31:36

标签: sql nested metadata google-bigquery

我是BigQuery(和sql)的新手,我正在尝试设置一个表,其中每行包含message列(字符串)和metadata列(重复)。我想使用元数据列,以便查询与某些元数据参数匹配的消息。

例如,我的消息字符串是:

Hi honey, I'm home!

,元数据列是描述消息的任意键/值对:

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

这将允许我向bigquery提出:

返回所有category personal (或message_type personal等消息的消息

重申一下,对于插入的每个消息行,元数据键可能会有所不同(例如,新行的元数据键可能为favorite_color而不是category)。

这是我想出的架构,以支持我想要的元数据灵活性:

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

模式要求每个元数据条目/行包含一个名为key的列和名为value的列。它似乎工作正常。

有趣的是,Bigquery将我的消息行表示为两行(我猜这叫做"展平"?):

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

我想出了如何查询单个元数据值,例如category = personal

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

我回来了一行:

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

太好了!但是,我不知道如何构建一个与多个元数据参数匹配的更复杂的查询,例如:

向我提取所有category personalmessage_type salutation

的邮件

以下查询不会返回任何内容:

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

我认为这是因为bigquery将我的单个消息行分解为两行(每个嵌套元数据行一行)。这显然意味着我的查询永远不能匹配单行,因为我试图匹配两个不同的元数据行(即我要求metadata.key同时等于两个不同的值,和metadata.value同时等于不同的值)。所以我对如何恰当地构建我的查询感到有点困惑。

理想情况下,我希望BigQuery返回单个行(我开始使用的原始示例行),因为它满足了我的查询的两个元数据要求。

我认为我需要GROUP BY,FLATTEN,WITHIN,unflatten等的组合。对于这个sql / bigquery新手来说,可能性/结构的组合有点令人生畏。任何帮助表示赞赏:)

1 个答案:

答案 0 :(得分:5)

尝试下面 - 只有一个选项
它总结了你在每一行中有多少“匹配,如果所有(在这种情况下为2)它输出它。非常简单

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

清洁版本如下

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