查询 BigQuery nested/repeated 个字段
Query BigQuery nested/repeated fields
我是 BigQuery(和 sql)的新手,我正在尝试设置一个 table,其中每行包含一个 message
列(字符串)和 metadata
列(重复)。我想使用元数据列,以便查询与某些元数据参数匹配的消息。
比如我的消息字符串是:
Hi honey, I'm home!
并且元数据列是描述消息的任意 key/value 对:
{"category": "personal",
"message_type": "salutation"}
这样我就可以请求 bigquery 来:
return 我所有 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"}]}
]
架构期望每个元数据 entry/row 包含一个名为 key
的列和一个名为 value
的列。它似乎工作正常。
有趣的是,Bigquery 将我的消息行表示为两行(我猜这叫做 "flattening"?):
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
为 personal
且 message_type
为 salutation
的消息
以下查询没有 return 任何内容:
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 return 一个 单行 行(我开始使用的原始示例行),因为它满足我查询的两个元数据要求.
我想我需要一些 GROUP BY、FLATTEN、WITHIN、unflatten 等的组合。possibilities/structure 的组合对于这个 sql/bigquery 新手来说有点令人生畏。任何帮助表示赞赏:)
尝试以下 - 只是选项之一
它总结了每行中有多少“匹配项”,如果全部(在本例中为 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
我是 BigQuery(和 sql)的新手,我正在尝试设置一个 table,其中每行包含一个 message
列(字符串)和 metadata
列(重复)。我想使用元数据列,以便查询与某些元数据参数匹配的消息。
比如我的消息字符串是:
Hi honey, I'm home!
并且元数据列是描述消息的任意 key/value 对:
{"category": "personal",
"message_type": "salutation"}
这样我就可以请求 bigquery 来:
return 我所有 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"}]}
]
架构期望每个元数据 entry/row 包含一个名为 key
的列和一个名为 value
的列。它似乎工作正常。
有趣的是,Bigquery 将我的消息行表示为两行(我猜这叫做 "flattening"?):
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
为 personal
且 message_type
为 salutation
以下查询没有 return 任何内容:
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 return 一个 单行 行(我开始使用的原始示例行),因为它满足我查询的两个元数据要求.
我想我需要一些 GROUP BY、FLATTEN、WITHIN、unflatten 等的组合。possibilities/structure 的组合对于这个 sql/bigquery 新手来说有点令人生畏。任何帮助表示赞赏:)
尝试以下 - 只是选项之一
它总结了每行中有多少“匹配项”,如果全部(在本例中为 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