我正在尝试使用以下架构将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
}
}
key_e下的键是动态的,即在一个响应中key_e将包含key_f和key_g,而对于另一个响应,它将包含key_h和key_i。可以随时创建新密钥,因此我无法为所有可能的密钥创建具有可空字段的记录。
相反,我想创建一个具有JSON数据类型的列,然后可以使用JSON_EXTRACT()函数查询该列。我已经尝试将key_e作为具有STRING数据类型的列加载,但是value_e被分析为JSON,因此失败。
如果没有JSON数据类型,如何将一部分JSON加载到单个BigQuery列中?
答案 0 :(得分:10)
将你的JSON作为BigQuery中的单个字符串列是definitelly的一个选项。如果您拥有大量数据,最终会导致查询价格过高,因为所有数据都会在一列中结束,实际查询逻辑会变得非常混乱。
如果你有轻微改变你的"设计" - 我建议考虑下面一个 - 在这里你可以采用重复模式
表架构:
[
{ "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"}
]
}
]
要加载的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"}]}
请注意:它应该是换行符分隔的JSON,因此每行必须在一行
答案 1 :(得分:3)
你不能用BigQuery直接做这个,但你可以让它在两个过程中工作:
(1)将您的JSON数据导入为具有单个字符串列的CSV文件。
(2)转换每一行以将“any-type”字段打包成字符串。编写一个UDF,它接受一个字符串并发出你想要的最后一列。将此查询的输出附加到目标表。
示例强>
我将从一些JSON开始:
{"a": 0, "b": "zero", "c": { "woodchuck": "a"}}
{"a": 1, "b": "one", "c": { "chipmunk": "b"}}
{"a": 2, "b": "two", "c": { "squirrel": "c"}}
{"a": 3, "b": "three", "c": { "chinchilla": "d"}}
{"a": 4, "b": "four", "c": { "capybara": "e"}}
{"a": 5, "b": "five", "c": { "housemouse": "f"}}
{"a": 6, "b": "six", "c": { "molerat": "g"}}
{"a": 7, "b": "seven", "c": { "marmot": "h"}}
{"a": 8, "b": "eight", "c": { "badger": "i"}}
将其作为带有单个STRING列的CSV导入BigQuery(我称之为'blob')。我不得不将分隔符设置为任意且不太可能的东西(刺 - 'þ')或它超过默认','。
验证您的表格是否正确导入。您应该看到简单的单列架构,预览看起来就像源文件一样。
接下来,我们编写一个查询,将其转换为您想要的形状。对于此示例,我们想要以下架构:
a (INTEGER)
b (STRING)
c (STRING -- packed JSON)
我们可以使用UDF执行此操作:
// Map a JSON string column ('blob') => { a (integer), b (string), c (json-string) }
bigquery.defineFunction(
'extractAndRepack', // Name of the function exported to SQL
['blob'], // Names of input columns
[{'name': 'a', 'type': 'integer'}, // Output schema
{'name': 'b', 'type': 'string'},
{'name': 'c', 'type': 'string'}],
function (row, emit) {
var parsed = JSON.parse(row.blob);
var repacked = JSON.stringify(parsed.c);
emit({a: parsed.a, b: parsed.b, c: repacked});
}
);
以及相应的查询:
SELECT a, b, c FROM extractAndRepack(JsonAnyKey.raw)
现在您只需要运行查询(选择所需的目标表),您就可以使用自己喜欢的形式获取数据。
Row a b c
1 0 zero {"woodchuck":"a"}
2 1 one {"chipmunk":"b"}
3 2 two {"squirrel":"c"}
4 3 three {"chinchilla":"d"}
5 4 four {"capybara":"e"}
6 5 five {"housemouse":"f"}
7 6 six {"molerat":"g"}
8 7 seven {"marmot":"h"}
9 8 eight {"badger":"i"}
答案 2 :(得分:2)
一种方法是将此文件加载为CSV而不是JSON(并引用值或消除中间的换行符),然后它将成为BigQuery中的单个STRING列。
P.S。你是正确的,拥有原生JSON数据类型会使这个场景更自然,BigQuery团队非常清楚它。