bigquery加入嵌套重复

时间:2016-03-11 00:24:06

标签: google-bigquery google-cloud-platform

我无法加入重复的嵌套字段,同时仍保留BigQuery中的原始行结构。

对于我的示例,我会将两个表称为AB

表A中的记录如下所示:

{
  "url":"some url",
  "repeated_nested": [
    {"key":"some key","property":"some property"}
  ]
}

表B中的记录如下所示:

{
  "key":"some key",
  "property2": "another property"
}

我希望找到一种方法将这些数据连接在一起,以生成如下所示的行:

{
  "url":"some url",
  "repeated_nested": [
    {
      "key":"some key",
      "property":"some property",
      "property2":"another property"
    }
  ]
}

我尝试的第一个查询是:

SELECT 
  url, repeated_nested.key, repeated_nested.property, repeated_nested.property2
FROM A
  AS lefttable
LEFT OUTER JOIN B
  AS righttable
  ON lefttable.key=righttable.key

这不起作用,因为BQ无法连接重复的嵌套字段。每行没有唯一标识符。如果我在FLATTEN上进行repeated_nested,那么我不确定如何正确地将原始行重新组合在一起。

数据使得url始终与其具有相同的repeated_nested字段。因此,我能够使用UDF进行解决方法,将这个重复的嵌套对象整理成JSON字符串,然后再次展开它:

SELECT url, repeated_nested.key, repeated_nested.property, repeated_nested.property2

FROM
JS(
   (
    SELECT basetable.url as url, repeated_nested
    FROM A as basetable

    LEFT JOIN (
      SELECT url, CONCAT("[", GROUP_CONCAT_UNQUOTED(repeated_nested_json, ","), "]") as repeated_nested
      FROM
      (
        SELECT
          url,
            CONCAT(
              '{"key": "', repeated_nested.key, '",',
              ' "property": "', repeated_nested.property, '",',
              ' "property2": "', mapping_table.property2, '"',
              '}'
            )
          ) as repeated_nested_json
        FROM (
          SELECT
            url, repeated_nested.key, repeated_nested.property
          FROM A
          GROUP BY url, repeated_nested.key, repeated_nested.property
        ) as urltable

         LEFT OUTER JOIN [SDF.alchemy_to_ric]
            AS mapping_table
            ON urltable.repeated_nested.key=mapping_table.key
      )
      GROUP BY url
    ) as companytable
    ON basetable.url = urltable.url
  ),

  // input columns:
  url, repeated_nested_json,

  // output schema:
  "[{'name': 'url', 'type': 'string'},
   {'name': 'repeated_nested_json', 'type': 'RECORD', 'mode':'REPEATED', 'fields':
    [ { 'name': 'key', 'type':'string' },
      { 'name': 'property', 'type':'string' },
      { 'name': 'property2', 'type':'string' }]
   }]",

  // UDF:
  "function(row, emit) {
    parsed_repeated_nested = [];
    try {
      if ( row.repeated_nested_json != null ) {
          parsed_repeated_nested = JSON.parse(row.repeated_nested_json);
      }
    } catch (ex) { }

    emit({
      url: row.url,
      repeated_nested: parsed_repeated_nested
    });
  }"
)

此解决方案适用于小型表。但是我正在使用的真实生活表中的列数比上面的例子多了很多。当除urlrepeated_nested_json之外还有其他字段时,它们都必须通过UDF传递。当我使用大约50 gb范围的表时,一切都很好。但是,当我将UDF和查询应用于500-1000 GB的表时,我从BQ收到内部服务器错误。

最后,我只需要GCS中新行分隔的JSON格式的所有数据。作为最后的努力,我尝试将所有字段连接成一个JSON字符串(这样我只有一列)希望我可以将其导出为CSV并拥有我需要的东西。但是,导出过程转义了双引号并在JSON字符串周围添加了双引号。根据BQ关于工作的文档(https://cloud.google.com/bigquery/docs/reference/v2/jobs),有一个属性configuration.query.tableDefinitions.(key).csvOptions.quote可以帮助我。但我无法弄清楚如何让它发挥作用。

是否有人就他们如何应对这种情况提出建议?

2 个答案:

答案 0 :(得分:1)

我从来没有这样做,但您应该能够使用flatten,然后加入,然后使用nest重新获得重复字段。

文档声明BigQuery总是会使查询结果变得扁平化,但这似乎是错误的:如果设置目标表,则可以选择不使结果变平。然后,您应该能够将该表作为JSON导出到存储。

另请参阅this answer了解如何让nest工作。

答案 1 :(得分:0)

@AndrewBackes - 本周我们针对UDF内存相关问题推出了一些修复程序;这里有一些关于根本原因的详细信息https://stackoverflow.com/a/36275462/5265394https://stackoverflow.com/a/35563562/5265394

您的查询的UDF版本现在正在为我工​​作;你可以验证一下吗?