【发布时间】:2021-05-03 17:05:30
【问题描述】:
我从 API 调用中提取数据并将其加载到 JSON 中,然后再将其加载到 bigquery 表中。我注意到有些字段同时包含数字和字符串,但是,在每日负载的基础上,它可能不会同时包含两者,因此 JSON 架构会根据当天包含的内容将该字段推断为 INTEGER 或 STRING。
BigQuery 表将此字段作为字符串...。有没有办法在加载之前在 BigQuery 的 LoadJobConfig 中将这个字段转换为 JSON 中的字符串?否则我会收到“提供的架构在某些日子与表不匹配错误”。
我对这一切都很陌生,所以我不确定是否有更好的方法。
这是我的 API 调用:
response = requests.post(url, json=data, headers=headers)
j = json.loads(response.text)
return j
然后我加载结果 vi:
def insert_rows_append(table_name, rows):
bq_client = get_big_query_client()
print('Inserting {} rows into {}'.format(table_name, len(rows)))
job_config = bigquery.LoadJobConfig()
# job_config.autodetect = True
job_config.write_disposition = "WRITE_APPEND"
job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON
# bq_table = bq_client.table(ORDERS_TABLE)
try:
load_job = bq_client.load_table_from_json(
rows,
table_name,
job_config=job_config
#, row_ids=[None] * len(rows_to_insert)
)
for row in rows:
if 'ad_name' in row:
if not isinstance(row['ad_name'], str): row['ad_name'] = str(row['ad_name'])
if 'ad_group' in row:
if not isinstance(row['ad_group'], str): row['ad_group'] = str(row['ad_group'])
我做了一些额外的检查。使用以下方法检查我传递给load_job = bq_client.load_table_from_json 的“行”:
def getList(dict):
for key, value in dict.items():
print(key, type(value))
print(getList(rows[0]))
Inserting dev:test.table rows into 29090
ad <class 'str'>
ad_group <class 'str'>
ad_group_name <class 'str'>
ad_name <class 'str'>
browser <class 'str'>
campaign <class 'str'>
campaign_name <class 'str'>
click_through_rate <class 'NoneType'>
clicked_at_date <class 'str'>
clicked_at_hour <class 'int'>
clicks <class 'int'>
clicks_unique <class 'int'>
cost_amount <class 'float'>
cost_currency <class 'str'>
country <class 'str'>
goal_rate <class 'NoneType'>
goal_revenue_amount <class 'NoneType'>
goal_revenue_currency <class 'NoneType'>
goals <class 'list'>
impressions <class 'int'>
impressions_unique <class 'int'>
influencer <class 'str'>
network <class 'str'>
network_name <class 'str'>
sub1 <class 'str'>
sub2 <class 'str'>
sub3 <class 'str'>
sub4 <class 'str'>
sub5 <class 'str'>
team_id <class 'int'>
team_name <class 'str'>
user_id <class 'str'>
network_click_through_rate <class 'NoneType'>
network_clicks <class 'NoneType'>
network_cost_amount <class 'NoneType'>
network_cost_currency <class 'NoneType'>
network_impressions <class 'NoneType'>
None
error occurred
400 Provided Schema does not match Table dev:test.table. Field ad_name has changed type from STRING to INTEGER
所以据此,JSON 中的 ad_name 是一个字符串。所以我不知道 INTEGER 是从哪里来的。
编辑:查看字段的值。我没有看到 ad_name 列的类型和字符串类型值。在字段中没有类型的情况下,python 是否将字段归类为 INTEGER?
【问题讨论】:
-
这是一个非常可靠的问题,但它需要 API 调用、JSON 和示例错误。换句话说,考虑添加一个 MRE,一个最小的可重现示例。
-
更新了帖子。对这一切都超级陌生,所以如果还有什么遗漏,请告诉我。
-
由于您正在执行
write_append,Bigquery 将不支持动态更新列的数据类型。加载前可以不更新json数据吗? -
@PeterJeong 好多了!
-
@AnkurSaxena 我接受了 yoru 的建议,但 atm 遇到了一些麻烦。这就是我将值转换为字符串的方法:``` for row in result['results']: if "ad_name" in row: row['ad_name'] == str(row['ad_name'] ) ``` 这似乎并没有被覆盖。
标签: python google-cloud-platform google-bigquery