我正在试图弄清楚如何将GCS中的CSV文件加载到BigQuery中。管道如下:
// Create the pipeline
Pipeline p = Pipeline.create(options);
// Create the PCollection from csv
PCollection<String> lines = p.apply(TextIO.read().from("gs://impression_tst_data/incoming_data.csv"));
// Transform into TableRow
PCollection<TableRow> row = lines.apply(ParDo.of(new StringToRowConverter()));
// Write table to BigQuery
row.apply(BigQueryIO.<TableRow>writeTableRows()
.to(“project_id:dataset.table”)
.withSchema(getSchema())
.withWriteDisposition(WriteDisposition.WRITE_APPEND)
.withCreateDisposition(CreateDisposition.CREATE_IF_NEEDED));
这是我在ParDo中使用的StringToRowConverter类来创建TableRow PCollection:
// StringToRowConverter
static class StringToRowConverter extends DoFn<String, TableRow> {
@ProcessElement
public void processElement(ProcessContext c) {
c.output(new TableRow().set("string_field", c.element()));
}
}
查看暂存文件,看起来这样会创建一个JSON的TableRows,它将csv集中到一个名为“string_field”的列中。如果我没有在模式中定义string_field,则作业失败。当我确定string_field时,它会将CSV的每一行写入列中,并将架构中定义的所有其他列留空。我知道这是预期的行为。
所以我的问题:如何获取此JSON输出并将其写入模式?下面的示例输出和架构......
"string_field": "6/26/17 21:28,Dave Smith,1 Learning Drive,867-5309,etc"}
架构:
static TableSchema getSchema() {
return new TableSchema().setFields(new ArrayList<TableFieldSchema>() {
// Compose the list of TableFieldSchema from tableSchema.
{
add(new TableFieldSchema().setName("Event_Time").setType("TIMESTAMP"));
add(new TableFieldSchema().setName("Name").setType("STRING"));
add(new TableFieldSchema().setName("Address").setType("STRING"));
add(new TableFieldSchema().setName("Phone").setType("STRING"));
add(new TableFieldSchema().setName("etc").setType("STRING"));
}
});
}
有没有比使用StringToRowConverter更好的方法呢?
我需要使用ParDo创建TableRow PCollection才能将其写入BQ。但是,我无法找到如何接受CSV PCollection,转换为TableRow并将其写出来的可靠示例。
是的,我是一个努力在这里学习的菜鸟。我希望有人可以用一个片段来帮助我,或者以最简单的方式指出我正确的方向。提前谢谢。
答案 0 :(得分:1)
StringToRowConverter
DoFn
中的代码应解析字符串并生成包含多个字段的TableRow
。由于每一行都以逗号分隔,这可能涉及在逗号上拆分字符串,然后使用您对列顺序的了解来执行以下操作:
String inputLine = c.element();
// May need to make the line parsing more robust, depending on your
// files. Look at how to parse rows of a CSV using Java.
String[] split = inputLine.split(',');
// Also, you may need to handle errors such as not enough columns, etc.
TableRow output = new TableRow();
output.set("Event_Time", split[0]); // may want to parse the string
output.set("Name", split[1]);
...
c.output(output);