将嵌套数组加载到 bigquery

Posted

技术标签:

【中文标题】将嵌套数组加载到 bigquery【英文标题】:load nested arrays into bigquery 【发布时间】:2016-08-21 13:08:39 【问题描述】:

我有 JSON 格式的数据,其中包含嵌套数组。这是一个例子:

"data": "events": [[1, 1271, 518, 945], [1, 1287, 495, 963],...

子数组的长度可以是 3 或 4,第一个数字是数据类型(大约有 30 种不同的)。有什么方法可以在不转换成字典“记录”的情况下将这些数据加载到 bigQuery?

谢谢, 亚龙

--编辑--

有this 的问题,有一个解决方法,但是有一个固定长度的子数组,所以我猜不适用..

【问题讨论】:

目前还不清楚决赛桌的预期 - 提供示例! 【参考方案1】:

这可能是错误的方向,因为尚不完全清楚您的最终目标是什么,但让我尝试帮助您 不知何故,我觉得您的目标表应如下所示

type    metric1 metric2 metric3  
   1       1271     518     945  
   1       1287     495     963  

所以,我的建议是分两步完成

第 1 步 - 将数据加载为 CSV,仅包含一个字段 - 假设表格 theTable 包含字段 data

                              data
 "data": "events": [[1, 1271, 518, 945], [1, 1287, 495, 963]]
 "data": "events": [[2, 111, 222, 333], [3, 444, 555, 666], [4, 777, 888, 999]] 

第 2 步 - 处理 theTable 以生成预期的架构(请参阅答案顶部)并保存到最终表格中。您可以为此使用以下查询

SELECT
  NTH(1, SPLIT(y)) AS type,
  NTH(2, SPLIT(y)) AS metric1,
  NTH(3, SPLIT(y)) AS metric2,
  NTH(4, SPLIT(y)) AS metric3,
FROM (
  SELECT 
    REPLACE(REPLACE(COALESCE(y0, y1, y2, y3, y4, y5, y6), '[', ''), ']', '') AS y  
  FROM (
    SELECT
      IF(k=0, JSON_EXTRACT(data, '$.data.events[0]'), NULL) AS y0,
      IF(k=1, JSON_EXTRACT(data, '$.data.events[1]'), NULL) AS y1,
      IF(k=2, JSON_EXTRACT(data, '$.data.events[2]'), NULL) AS y2,
      IF(k=3, JSON_EXTRACT(data, '$.data.events[3]'), NULL) AS y3,
      IF(k=4, JSON_EXTRACT(data, '$.data.events[4]'), NULL) AS y4,
      IF(k=5, JSON_EXTRACT(data, '$.data.events[5]'), NULL) AS y5,
      IF(k=6, JSON_EXTRACT(data, '$.data.events[6]'), NULL) AS y6,
    FROM theTable AS a
    CROSS JOIN (
      SELECT k FROM (SELECT 0 AS k), (SELECT 1 AS k), (SELECT 2 AS k), 
      (SELECT 3 AS k), (SELECT 4 AS k), (SELECT 5 AS k), (SELECT 6 AS k)
    ) AS b
  )
  HAVING NOT y IS NULL
)

结果将是

type    metric1 metric2 metric3  
   1       1271     518     945  
   1       1287     495     963  
   2        111     222     333  
   3        444     555     666  
   4        777     888     999  

如您所见 - 此特定查询最多支持 7 个子数组,但您可以通过更改三个位置的代码来减少或增加它

#1

REPLACE(REPLACE(COALESCE(y0, y1, y2, y3, y4, y5, y6), '[', ''), ']', '') AS y    

#2

IF(k=0, JSON_EXTRACT(data, '$.data.events[0]'), NULL) AS y0,
IF(k=1, JSON_EXTRACT(data, '$.data.events[1]'), NULL) AS y1,
IF(k=2, JSON_EXTRACT(data, '$.data.events[2]'), NULL) AS y2,
IF(k=3, JSON_EXTRACT(data, '$.data.events[3]'), NULL) AS y3,
IF(k=4, JSON_EXTRACT(data, '$.data.events[4]'), NULL) AS y4,
IF(k=5, JSON_EXTRACT(data, '$.data.events[5]'), NULL) AS y5,
IF(k=6, JSON_EXTRACT(data, '$.data.events[6]'), NULL) AS y6,

#3

SELECT k FROM (SELECT 0 AS k), (SELECT 1 AS k), (SELECT 2 AS k), 
(SELECT 3 AS k), (SELECT 4 AS k), (SELECT 5 AS k), (SELECT 6 AS k)

最后,只测试转换逻辑,不加载实际数据 - 你可以使用下面的脚本

SELECT
  NTH(1, SPLIT(y)) AS type,
  NTH(2, SPLIT(y)) AS metric1,
  NTH(3, SPLIT(y)) AS metric2,
  NTH(4, SPLIT(y)) AS metric3,
FROM (
  SELECT 
    REPLACE(REPLACE(COALESCE(y0, y1, y2, y3, y4, y5, y6), '[', ''), ']', '') AS y  
  FROM (
    SELECT
      IF(k=0, JSON_EXTRACT(data, '$.data.events[0]'), NULL) AS y0,
      IF(k=1, JSON_EXTRACT(data, '$.data.events[1]'), NULL) AS y1,
      IF(k=2, JSON_EXTRACT(data, '$.data.events[2]'), NULL) AS y2,
      IF(k=3, JSON_EXTRACT(data, '$.data.events[3]'), NULL) AS y3,
      IF(k=4, JSON_EXTRACT(data, '$.data.events[4]'), NULL) AS y4,
      IF(k=5, JSON_EXTRACT(data, '$.data.events[5]'), NULL) AS y5,
      IF(k=6, JSON_EXTRACT(data, '$.data.events[6]'), NULL) AS y6,
    FROM (
    SELECT data FROM 
      (SELECT '"data": "events": [[1, 1271, 518, 945], [1, 1287, 495, 963]]' AS data),
      (SELECT '"data": "events": [[2, 111, 222, 333], [3, 444, 555, 666], [4, 777, 888, 999]]' AS data) 
    ) AS a
    CROSS JOIN (
      SELECT k FROM (SELECT 0 AS k), (SELECT 1 AS k), (SELECT 2 AS k), 
      (SELECT 3 AS k), (SELECT 4 AS k), (SELECT 5 AS k), (SELECT 6 AS k)
    ) AS b
  )
  HAVING NOT y IS NULL
)

希望这对您有所帮助!

【讨论】:

【参考方案2】:

无法直接加载数组数组;您需要使用记录来包装数组的内部级别。标准 SQL 的参考涉及到这一点(尽管就语言本身而言,而不是加载数据):https://cloud.google.com/bigquery/sql-reference/arrays#building_arrays_of_arrays。

【讨论】:

感谢您的回答。我试图避免对数据进行转换以将其转换为记录/结构。有没有办法将此嵌套数组作为字符串/文本 blob 上传? 这个过去的问题可能会有所帮助:***.com/questions/37660579/… 您可以将其加载为字符串,然后使用 BigQuery 的 JSON 函数提取您想要作为查询一部分的部分。 我有个小结题,只想把嵌套数组加载到BQ中。 json 行看起来像 "data": "events": [[1, 1271, 518, 945], [1, 1287, 495, 963]] 我想将它加载到 BQ 中

以上是关于将嵌套数组加载到 bigquery的主要内容,如果未能解决你的问题,请参考以下文章

获取嵌套数组项以附加到 HTML 表中的新列

如何使用 pyspark 在 aws 胶水中展平嵌套 json 中的数组?

数据加载器解析嵌套数组

访问被拒绝:BigQuery BigQuery:写入数据时权限被拒绝

将嵌套结构中的数组附加到另​​一个嵌套结构中的另一个数组

使用 Java 将嵌套地图保存并加载到文本文件中