将无效的 JSON 列存储为 STRING 或在 BigQuery 中跳过它们

Store invalid JSON columns are STRING or skip them in BigQuery

我有一个 JSON 数据文件,如下所示

{
    "key_a": "value_a",
    "key_b": "value_b",
    "key_c": {
        "c_nested/invalid.key.according.to.bigquery": "valid_value_though"
    }
}

我们知道 BigQuery 将 c_nested/invalid.key.according.to.bigquery 视为无效的列名。我有大量日志数据由 StackDriver 导出到 Google Cloud Storage,其中有很多无效字段(根据 BigQuery Fields must contain only letters, numbers, and underscores, start with a letter or underscore, and be at most 128 characters long).

作为一种解决方法,我尝试将值存储到 key_c(整个 {"c_nested/invalid.key.according.to.bigquery": "valid_value_though"} 事物)作为 BigQuery table.

中的字符串

我假设我的 table 定义如下所示:

[
    {
        "mode": "NULLABLE", 
        "name": "key_a", 
        "type": "STRING"
    },
    {
        "mode": "NULLABLE", 
        "name": "key_b", 
        "type": "STRING"
    },
    {
        "mode": "NULLABLE", 
        "name": "key_c", 
        "type": "STRING"
    }
]

当我尝试使用此架构创建 table 时,出现以下错误:

Error while reading data, error message: JSON table encountered too many errors, giving up. Rows: 1; errors: 1. Please look into the errors[] collection for more details.

Error while reading data, error message: JSON processing encountered too many errors, giving up. Rows: 1; errors: 1; max bad: 0; error percent: 0

Error while reading data, error message: JSON parsing error in row starting at position 0: Expected key

假设它现在在 BigQuery 中受支持,我想简单地跳过具有以下架构的 key_c 列:

[
    {
        "mode": "NULLABLE", 
        "name": "key_a", 
        "type": "STRING"
    },
    {
        "mode": "NULLABLE", 
        "name": "key_b", 
        "type": "STRING"
    }
]

上面的模式至少让我创建了一个永久的 table(用于查询外部数据),但是当我尝试查询数据时,我得到以下错误:

Error while reading table: 
projectname.dataset_name.table_name, error message: 
JSON parsing error in row starting at position 0: No such field: key_c.

我知道 here 描述了一种方法 将每个 JSON 行原始加载到 BigQuery - 就好像它是 CSV - 然后在 BigQuery 中解析 但是帽子让查询变得太复杂了。

清理数据是唯一的方法吗?我该如何解决这个问题?

我正在寻找一种方法来跳过为无效字段创建列,然后直接将其存储为字符串或完全忽略它们。这可能吗?

人们使用 BQ(和其他云数据库)的主要前提之一是存储便宜。在实践中,将 'raw' 或 'source' 数据加载到 BQ 中,然后根据需要进行转换(视图或其他转换工具)通常很有帮助。这是从 ETLELT 的范式转变。

考虑到这一点,我会将您的 "invalid" JSON blob 作为字符串导入,然后在您的转换步骤中对其进行解析。这是一种方法:

 with data as (select '{"key_a":"value_a","key_b":"value_b","key_c":{"c_nested/invalid.key.according.to.bigquery":"valid_value_though"}}' as my_string)
select 
  JSON_EXTRACT_SCALAR(my_string,'$.key_a') as key_a,
  JSON_EXTRACT_SCALAR(my_string,'$.key_b') as key_b,
  JSON_EXTRACT_SCALAR(REPLACE(my_string,"c_nested/invalid.key.according.to.bigquery","custom_key"),'$.key_c.custom_key') as key_c
from data