情况如下:
我的 BigQuery TableSchema 如下:
{
"name": "Id",
"type": "INTEGER",
"mode": "nullable"
},
{
"name": "Address",
"type": "RECORD",
"mode": "repeated",
"fields":[
{
"name": "Street",
"type": "STRING",
"mode": "nullable"
},
{
"name": "City",
"type": "STRING",
"mode": "nullable"
}
]
}
我正在从Google云端存储存储桶中读取数据,并使用云端功能写入BigQuery。
我已将云功能中的TableSchema定义为:
table_schema = bigquery.TableSchema()
Id_schema = bigquery.TableFieldSchema()
Id_schema.name = 'Id'
Id_schema.type = 'INTEGER'
Id_schema.mode = 'nullable'
table_schema.fields.append(Id_schema)
Address_schema = bigquery.TableFieldSchema()
Address_schema.name = 'Address'
Address_schema.type = 'RECORD'
Address_schema.mode = 'repeated'
Street_schema = bigquery.TableFieldSchema()
Street_schema.name = 'Street'
Street_schema.type = 'STRING'
Street_schema.mode = 'nullable'
Address_schema.fields.append(Street_schema)
table_schema.fields.append(Address_schema)
City_schema = bigquery.TableFieldSchema()
City_schema.name = 'City'
City_schema.type = 'STRING'
City_schema.mode = 'nullable'
Address_schema.fields.append(City_schema)
table_schema.fields.append(Address_schema)
我的数据文件如下所示:(每行都是json)
{"Id": 1, "Address": {"Street":"MG Road","City":"Pune"}}
{"Id": 2, "Address": {"City":"Mumbai"}}
{"Id": 3, "Address": {"Street":"XYZ Road"}}
{"Id": 4}
{"Id": 5, "PhoneNumber": 12345678, "Address": {"Street":"ABCD Road", "City":"Bangalore"}}
问题: 当传入数据有一些丢失的密钥时,我该如何处理? 例如,
"Street"
的第2行缺失"City"
的第3行"Address"
的第4行"PhoneNumber"
的第5行显示.. 问题1 :如果丢失数据(例如,第2行,第3行,第4行),如何处理WriteToBigQuery
问题2 :如果新数据显示在数据中,如何处理? 例如,
"PhoneNumber"
出现..
如何在运行中在BigQuery表中添加新列?
(为了适应这些新添加的字段,我是否必须首先详尽地定义BigQuery表模式?)问题3 :如何遍历传入数据文件的每一行(同时读取数据文件)并确定要解析的字段?
答案 0 :(得分:2)
对您而言,其中一个选项是 - 我建议您只使用类型为line
的一个字段string
将数据写入表中,而不是使用架构更改,并在运行期间应用架构逻辑查询
下面的示例是关于如何在一个字段中对整个行应用模式的BigQuery Standard SQL
#standardSQL
WITH t AS (
SELECT '{"Id": 1, "Address": {"Street":"MG Road","City":"Pune"}}' line UNION ALL
SELECT '{"Id": 2, "Address": {"City":"Mumbai"}}' UNION ALL
SELECT '{"Id": 3, "Address": {"Street":"XYZ Road"}}' UNION ALL
SELECT '{"Id": 4} ' UNION ALL
SELECT '{"Id": 5, "PhoneNumber": 12345678, "Address": {"Street":"ABCD Road", "City":"Bangalore"}}'
)
SELECT
JSON_EXTRACT_SCALAR(line, '$.Id') id,
JSON_EXTRACT_SCALAR(line, '$.PhoneNumber') PhoneNumber,
JSON_EXTRACT_SCALAR(line, '$[Address].Street') Street,
JSON_EXTRACT_SCALAR(line, '$[Address].City') City
FROM t
结果如下
Row id PhoneNumber Street City
1 1 null MG Road Pune
2 2 null null Mumbai
3 3 null XYZ Road null
4 4 null null null
5 5 12345678 ABCD Road Bangalore
我认为这种方法可以回答/解决您的所有四个问题
答案 1 :(得分:1)
问题:如何在传入数据缺少某些键时进行处理?
问题1 :如果缺少数据(例如,第2行,第3行,第4行),如何处理WriteToBigQuery
问题2 :如果新数据显示在数据中,如何处理?
我建议将JSON字符串解码为某些数据结构,例如自定义from setuptools import setup, find_packages
with open('requirements.txt') as f:
requirements = f.read().splitlines()
__version__ = "0.0.2"
setup(
version=__version__
name = "mymodules",
packages = find_packages(exclude=['tests', '*.tests', '*.tests.*']),
install_requires=requirements,
)
类,您可以在其中访问和操作成员变量,并定义哪些成员是可选的以及哪些是必需的。使用自定义类为您提供抽象级别,以便管道中的下游转换不需要担心如何操作JSON。可以实现下游转换以从Contact
对象构建TableRow
并且还遵循BigQuery表模式。此设计遵循一般抽象和关注点分离原则,并能够处理丢失或其他字段的所有场景。
问题3 :如何遍历传入数据文件的每一行(同时读取数据文件)并确定要解析的字段?
Dataflow执行管道会自动执行此操作。如果管道从Google云端存储中读取(例如,使用Contact
),则数据流将处理文件的每一行作为单个元素(单个JSON字符串)。确定要解析的字段是业务逻辑的详细信息,可以在解析JSON字符串的转换中定义。