我试图将以下模式的json加载到BigQuery中:
{
key_a:value_a,
key_b:{
key_c:value_c,
key_d:value_d
}
key_e:{
key_f:value_f,
key_g:value_g
}
}
Run Code Online (Sandbox Code Playgroud)
key_e下的键是动态的,即在一个响应中key_e将包含key_f和key_g,而对于另一个响应,它将包含key_h和key_i.可以随时创建新密钥,因此我无法为所有可能的密钥创建具有可空字段的记录.
相反,我想创建一个具有JSON数据类型的列,然后可以使用JSON_EXTRACT()函数查询该列.我已经尝试将key_e作为具有STRING数据类型的列加载,但value_e被分析为JSON,因此失败.
如果没有JSON数据类型,如何将一部分JSON加载到单个BigQuery列中?
Mik*_*ant 11
将JSON作为BigQuery中的单个字符串列是definitelly的一个选项.如果您拥有大量数据,最终会导致查询价格过高,因为所有数据都会在一列中结束,实际查询逻辑会变得非常混乱.
如果你有轻微改变你的"设计"的奢侈 - 我建议考虑下面的一个 - 在这里你可以采用REPEATED模式
表模式:
[
{ "name": "key_a",
"type": "STRING" },
{ "name": "key_b",
"type": "RECORD",
"mode": "REPEATED",
"fields": [
{ "name": "key",
"type": "STRING"},
{ "name": "value",
"type": "STRING"}
]
},
{ "name": "key_e",
"type": "RECORD",
"mode": "REPEATED",
"fields": [
{ "name": "key",
"type": "STRING"},
{ "name": "value",
"type": "STRING"}
]
}
]
Run Code Online (Sandbox Code Playgroud)
要加载的JSON示例
{"key_a": "value_a1", "key_b": [{"key": "key_c", "value": "value_c"}, {"key": "key_d", "value": "value_d"}], "key_e": [{"key": "key_f", "value": "value_f"}, {"key": "key_g", "value": "value_g"}]}
{"key_a": "value_a2", "key_b": [{"key": "key_x", "value": "value_x"}, {"key": "key_y", "value": "value_y"}], "key_e": [{"key": "key_h", "value": "value_h"}, {"key": "key_i", "value": "value_i"}]}
Run Code Online (Sandbox Code Playgroud)
请注意:它应该是换行符分隔的JSON,因此每行必须在一行上
您无法直接使用 BigQuery 执行此操作,但可以分两遍使其工作:
\n\n(1) 将 JSON 数据导入为具有单个字符串列的 CSV 文件。
\n\n(2) 转换每一行,将“任意类型”字段打包为字符串。编写一个 UDF,它接受一个字符串并发出您想要的最终列集。将此查询的输出附加到目标表。
\n\n例子
\n\n我将从一些 JSON 开始:
\n\n{"a": 0, "b": "zero", "c": { "woodchuck": "a"}}\n{"a": 1, "b": "one", "c": { "chipmunk": "b"}}\n{"a": 2, "b": "two", "c": { "squirrel": "c"}}\n{"a": 3, "b": "three", "c": { "chinchilla": "d"}}\n{"a": 4, "b": "four", "c": { "capybara": "e"}}\n{"a": 5, "b": "five", "c": { "housemouse": "f"}}\n{"a": 6, "b": "six", "c": { "molerat": "g"}}\n{"a": 7, "b": "seven", "c": { "marmot": "h"}}\n{"a": 8, "b": "eight", "c": { "badger": "i"}}\nRun Code Online (Sandbox Code Playgroud)\n\n将其作为具有单个 STRING 列的 CSV 导入 BigQuery(我称之为“blob”)。我必须将分隔符设置为任意且不太可能的字符(刺 - \'\xc3\xbe\'),否则它就会被默认的 \',\' 绊倒。
\n\n验证您的表导入正确。您应该看到简单的一列架构,并且预览应该看起来就像源文件一样。
\n\n接下来,我们编写一个查询将其转换为您想要的形状。对于此示例,我们需要以下架构:
\n\na (INTEGER)\nb (STRING)\nc (STRING -- packed JSON)\nRun Code Online (Sandbox Code Playgroud)\n\n我们可以使用 UDF 来做到这一点:\n
\n\n// Map a JSON string column (\'blob\') => { a (integer), b (string), c (json-string) }\nbigquery.defineFunction(\n \'extractAndRepack\', // Name of the function exported to SQL\n [\'blob\'], // Names of input columns\n [{\'name\': \'a\', \'type\': \'integer\'}, // Output schema\n {\'name\': \'b\', \'type\': \'string\'},\n {\'name\': \'c\', \'type\': \'string\'}],\n function (row, emit) {\n var parsed = JSON.parse(row.blob);\n var repacked = JSON.stringify(parsed.c);\n emit({a: parsed.a, b: parsed.b, c: repacked});\n }\n);\nRun Code Online (Sandbox Code Playgroud)\n\n以及相应的查询:
\n\n{"a": 0, "b": "zero", "c": { "woodchuck": "a"}}\n{"a": 1, "b": "one", "c": { "chipmunk": "b"}}\n{"a": 2, "b": "two", "c": { "squirrel": "c"}}\n{"a": 3, "b": "three", "c": { "chinchilla": "d"}}\n{"a": 4, "b": "four", "c": { "capybara": "e"}}\n{"a": 5, "b": "five", "c": { "housemouse": "f"}}\n{"a": 6, "b": "six", "c": { "molerat": "g"}}\n{"a": 7, "b": "seven", "c": { "marmot": "h"}}\n{"a": 8, "b": "eight", "c": { "badger": "i"}}\nRun Code Online (Sandbox Code Playgroud)\n\n现在您只需运行查询(选择所需的目标表),您就会获得您喜欢的形式的数据。
\n\nRow a b c \n1 0 zero {"woodchuck":"a"} \n2 1 one {"chipmunk":"b"} \n3 2 two {"squirrel":"c"} \n4 3 three {"chinchilla":"d"} \n5 4 four {"capybara":"e"} \n6 5 five {"housemouse":"f"} \n7 6 six {"molerat":"g"} \n8 7 seven {"marmot":"h"} \n9 8 eight {"badger":"i"} \nRun Code Online (Sandbox Code Playgroud)\n