BigQuery:创建JSON数据类型的列

Nat*_*anC 6 google-bigquery

我试图将以下模式的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,因此每行必须在一行上


Ada*_*ick 5

您无法直接使用 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"}}\n
Run Code Online (Sandbox Code Playgroud)\n\n

将其作为具有单个 STRING 列的 CSV 导入 BigQuery(我称之为“blob”)。我必须将分隔符设置为任意且不太可能的字符(刺 - \'\xc3\xbe\'),否则它就会被默认的 \',\' 绊倒。

\n\n

验证您的表导入正确。您应该看到简单的一列架构,并且预览应该看起来就像源文件一样。

\n\n

接下来,我们编写一个查询将其转换为您想要的形状。对于此示例,我们需要以下架构:

\n\n
a (INTEGER)\nb (STRING)\nc (STRING -- packed JSON)\n
Run 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);\n
Run 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"}}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在您只需运行查询(选择所需的目标表),您就会获得您喜欢的形式的数据。

\n\n
Row 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"}   \n
Run Code Online (Sandbox Code Playgroud)\n