BigQuery 中未嵌套的 json 对象的字符串化数组

Posted

技术标签:

【中文标题】BigQuery 中未嵌套的 json 对象的字符串化数组【英文标题】:Unnest stringified array of json objects in BigQuery 【发布时间】:2019-07-19 18:19:24 【问题描述】:

我有一个表,其中包含一个 string 列,其中包含一个 JSON 对象的字符串化列表,如下所示:

'["a": 5, "b": 6, "a": 7, "b": 8]'

我想取消嵌套这个数组,然后使用json_extract()json_extract_scalar() 从这些对象中获取值。

BigQuery's JSON Function documentation 不清楚我是否能够使用内置功能做到这一点。

是否需要 UDF 才能完成此操作,或者 BigQuery 中是否存在此功能?

下面的 UDF 完成了我正在寻找的内容:

CREATE TEMP FUNCTION
  JSON_EXTRACT_ARRAY(input STRING)
  RETURNS ARRAY<STRING>
  LANGUAGE js AS """  
return JSON.parse(input).map(x => JSON.stringify(x));
""";

with

raw as (
  select
    1 as id,
    '["a": 5, "b": 6, "a": 7, "b": 8]' as body
)

select
  id,
  json_extract(entry, '$.a') as a,
  json_extract(entry, '$.b') as b
from
  raw,
  unnest(json_extract_array(body)) as entry

【问题讨论】:

看起来你有解决方案 - 这里的问题是什么?您想要不涉及 UDF 的解决方案吗?或者是其他东西?请澄清-因为我仍然不清楚您突出显示/加粗的任何内容 请为issuetracker.google.com/issues/63716683投票 对不起,我以为我的问题很清楚。换种说法:“是否需要 UDF 才能完成此操作,或者 BigQuery 标准 SQL 是否支持取消嵌套字符串化 JSON 数组而不需要 UDF?” 我不清楚为什么这个问题被否决而没有提出什么可以使它变得更好的建议。对于遇到此问题的任何人来说,这仍然是一个合法的未决问题,尽管 Felipe Hoffa 的评论确实包含一个链接,如果有人想为其添加投票,则可以跟踪此缺失的功能。 【参考方案1】:

试试这样的


with

raw as (
    select
        1 as id,
        '["a": 5, "b": 6, "a": 7, "b": 8]' as body
)

select
    r.id,
    r.body,
    regexp_extract_all(r.body, r'(.*?)'),
    json_extract(entry, '$.a') as a,
    json_extract(entry, '$.b') as b
from
    raw as r
    cross join  unnest(
                    regexp_extract_all(r.body, r'(.*?)')
                ) as entry

或者更通用的解决方案

with

raw as (
    select
        1 as id,
        '["a": 5, "b": "x": 1, "y": 2, "b": "c": 5, "d": 8, "a": 7]' as body
)

select
    r.id,
    r.body,
    split(trim(r.body, '[]'), ', '),
    json_extract(concat('', entry, ''), '$.a') as a,
    json_extract(concat('', entry, ''), '$.b') as b
from
    raw as r
    cross join  unnest(
                    split(trim(r.body, '[]'), ', ')
                ) as entry

【讨论】:

这很好,示例代码按预期工作,无需求助于 UDF 即可解决问题。我会用这个来踢轮胎 - 谢谢!【参考方案2】:

Google 已将函数 JSON_EXTRACT_ARRAY 添加到其标准 SQL 中,因此现在无需 UDF 即可完成此操作。事实上,由于 OP 中的 UDF 名称是相同的名称 (JSON_EXTRACT_ARRAY),您可以按原样在 UDF 下运行该查询,它会起作用。

如果性能很重要,您也可以通过将正文数据提取到重复记录中来利用BigQuery's nesting capabilities,而不是完全非规范化表。

with 
    raw as (
        select
            1 as id,
            '["a": 5, "b": 6, "a": 7, "b": 8]' as body
    )

select
    r.id,
    array(
        select
            struct (
                json_value(items, '$.a') as a,
                json_value(items, '$.b') as b
            ) as b 
        from unnest(json_extract_array(body, '$')) as items
    ) as body_record_repeated
from raw r

会返回的

BigQuery repeated record result

【讨论】:

以上是关于BigQuery 中未嵌套的 json 对象的字符串化数组的主要内容,如果未能解决你的问题,请参考以下文章

Athena 在另一个 json 结构数组中未嵌套 json 字符串数组

处理 BigQuery 中未嵌套记录导致的重复行的最佳做法?

将数组保存到 BigQuery

取消嵌套存储在列中的 JSON 字符串 [BigQuery]

在 BigQuery 中取消嵌套 JSON 字符串化数组

在 BigQuery 中提取嵌套 Array/STRUCT JSON 字符串字段的组件