python - 加载到 BigQuery - 一列处理任意 json 字段(空数组、具有不同字段的字典等)

标签 python json google-bigquery schema

我们有以下三个 JSON,其数据应加载到同一个表中:

{ "name": "tom", "customValues": [] }
{ "name": "joe", "customValues": { "member": "1" } }
{ "name": "joe", "customValues": { "year": "2020", "number": "3" } }

我们使用 python bigquery.LoadJobConfig 函数加载数据:

job_config = bigquery.LoadJobConfig(
    schema=SCHEMA_MAP.get(bq_table) if autodetect == False else None,
    source_format=bigquery.SourceFormat.NEWLINE_DELIMITED_JSON,
    write_disposition=bigquery.WriteDisposition.WRITE_TRUNCATE if remove_old == True else bigquery.WriteDisposition.WRITE_APPEND,
    autodetect=autodetect
)

SCHEMA_MAP 是一个数组字典,其中架构中的每个数组都对应我们的一个表。我们使用 python bigquery.SchemaField 函数在 python 中定义 BigQuery 架构。如果上面的 3 个 JSON 中的每一个都进入 3 个不同的表,我会将它们的表架构定义为:

SCHEMA_T1 = [
    bigquery.SchemaField("name", "STRING"),
    bigquery.SchemaField("customValues", "STRING", mode="REPEATED")
]

SCHEMA_T2 = [
    bigquery.SchemaField("name", "STRING"),
    bigquery.SchemaField("customValues", "RECORD", mode="REPEATED", fields=[
        bigquery.SchemaField("member", "STRING")
    ])
]

SCHEMA_T3 = [
    bigquery.SchemaField("name", "STRING"),
    bigquery.SchemaField("customValues", "RECORD", mode="REPEATED", fields=[
        bigquery.SchemaField("year", "STRING"),
        bigquery.SchemaField("number", "STRING")
    ])
]

是否可以定义 customValues 列来在一个表中处理所有这 3 种不同的数据类型?如何为此定义模式?目前使用SCHEMA_T1,上传T2或T3形式的数据,上传失败,返回错误Error while read data,错误信息:JSON parsing error in rowstarting在位置 0:为非记录字段指定的 JSON 对象:customValues。其他模式的类似错误。 BigQuery 中是否有可用于此目的的通用 any json 字段?

最佳答案

由于 BigQuery 的 JSON 功能仍处于预览版中(请参阅 launch stages )。作为解决方法,您可以使用 bigquery 客户端中的 load_table_from_dataframe 从数据列加载数据,这些数据在推送到我们的工作表之前可能需要进行一些细化。

让我们看看您的场景,假设我们有一个包含原始数据的 data.json 文件:

data.json

[
    {
        "name": "tom",
        "customValues": []
    },
    {
        "name": "joe",
        "customValues": {
            "member": "1"
        }
    },
    {
        "name": "joe",
        "customValues": {
            "year": "2020",
            "number": "3"
        }
    }
]

我们有一个关于 bigquery 的表需要填充。

create or replace table "my-project.my-dataset.a-table" (
   name STRING,
   customValues STRING
)

load.py

from google.cloud import bigquery
import pandas as pd

client = bigquery.Client()

table_id = "project-id.dataset-id.a-table"
df = pd.read_json('data.json')
df["customValues"]= df["customValues"].apply(str)

print(df.shape)
print(df.head())

job_config = bigquery.LoadJobConfig(source_format=bigquery.SourceFormat.PARQUET, autodetect=True)
job = client.load_table_from_dataframe(df, table_id, job_config=job_config)
job.result() 

table = client.get_table(table_id)  
print("Loaded {} rows and {} columns to {}".format(table.num_rows, len(table.schema), table_id))

输出

| **name** | **customValues**                |
|----------|---------------------------------|
| tom      | []                              |
| joe      | {'member': '1'}                 |
| joe      | {'year': '2020', 'number': '3'} |

正如您所看到的,无论 customValues 的结构如何,我们都可以将其插入到我们的工作表(只有 2 列)中。我们将 json 数据加载到数据框中,然后使用 apply 更新数据类型列以适合我们的列类型。有关使用 apply 的更多信息,请访问此 link .

关于python - 加载到 BigQuery - 一列处理任意 json 字段(空数组、具有不同字段的字典等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71139537/

相关文章:

python - 如何在通过 Ctrl-v 选择的一堆行上调用函数?

google-bigquery - 如何从 ARRAY 中排除 NULL 以便查询不会失败

google-app-engine - 谷歌云数据流 ETL(数据存储 -> 转换 -> BigQuery)

python - Django:使用sqlite3作为数据库在Heroku上部署应用程序

python - learnpython.org 模块练习

python - 范围在 imshow() 中起什么作用?

android - 使用 JSON 将 ArrayList 从 Android 发送到 PHP 脚本

json - json 格式的 bash 变量

json - 不知道如何在Powershell中获取JSON对象的名称字段?

google-bigquery - 2 个 bigquery 时间戳字段之间的分钟差异