我将数据写入BigQuery并成功写入。但是我关注它的编写格式。
以下是我在BigQuery中执行任何查询时显示数据的格式:
检查第一行,SalesComponent的值是CPS_H但显示' BeamRecord [dataValues = [CPS_H'在ModelIteration中,值以方形braket结束。
以下是用于从BeamSql将数据推送到BigQuery的代码:
TableSchema tableSchema = new TableSchema().setFields(ImmutableList.of(
new TableFieldSchema().setName("SalesComponent").setType("STRING").setMode("REQUIRED"),
new TableFieldSchema().setName("DuetoValue").setType("STRING").setMode("REQUIRED"),
new TableFieldSchema().setName("ModelIteration").setType("STRING").setMode("REQUIRED")
));
TableReference tableSpec = BigQueryHelpers.parseTableSpec("beta-194409:data_id1.tables_test");
System.out.println("Start Bigquery");
final_out.apply(MapElements.into(TypeDescriptor.of(TableRow.class)).via(
(MyOutputClass elem) -> new TableRow().set("SalesComponent", elem.SalesComponent).set("DuetoValue", elem.DuetoValue).set("ModelIteration", elem.ModelIteration)))
.apply(BigQueryIO.writeTableRows()
.to(tableSpec)
.withSchema(tableSchema)
.withCreateDisposition(CreateDisposition.CREATE_IF_NEEDED)
.withWriteDisposition(WriteDisposition.WRITE_TRUNCATE));
p.run().waitUntilFinish();
编辑
我使用下面的代码将BeamRecord转换为MyOutputClass类型,这也不起作用:
PCollection<MyOutputClass> final_out = join_query.apply(ParDo.of(new DoFn<BeamRecord, MyOutputClass>() {
private static final long serialVersionUID = 1L;
@ProcessElement
public void processElement(ProcessContext c) {
BeamRecord record = c.element();
String[] strArr = record.toString().split(",");
MyOutputClass moc = new MyOutputClass();
moc.setSalesComponent(strArr[0]);
moc.setDuetoValue(strArr[1]);
moc.setModelIteration(strArr[2]);
c.output(moc);
}
}));
答案 0 :(得分:2)
看起来你的MyOutputClass
构造不正确(值不正确)。如果您查看它,BigQueryIO
能够创建具有正确字段的行。但那些领域的价值观错误。这意味着当您致电.set("SalesComponent", elem.SalesComponent)
时,elem
中的数据已经不正确。
我的猜测是,当您从BeamRecord
转换为MyOutputClass
时,问题出现在上一步中。如果您做了类似的事情(或者其他一些转换逻辑在幕后为您执行此操作),您将获得类似于您所看到的结果:
BeamRecord
将beamRecord.toString()
转换为字符串;
BeamRecord.toString()
实施,您可以看到您正在获得该字符串格式; ,
获取字符串数组; MyOutputClass
; Pseudocode就是这样的:
PCollection<MyOutputClass> final_out =
beamRecords
.apply(
ParDo.of(new DoFn() {
@ProcessElement
void processElement(Context c) {
BeamRecord record = c.elem();
String[] fields = record.toString().split(",");
MyOutputClass elem = new MyOutputClass();
elem.SalesComponent = fields[0];
elem.DuetoValue = fields[1];
...
c.output(elem);
}
})
);
做这样的事情的正确方法是在记录上调用getter而不是沿着这些行(伪代码)分割它的字符串表示:
PCollection<MyOutputClass> final_out =
beamRecords
.apply(
ParDo.of(new DoFn() {
@ProcessElement
void processElement(Context c) {
BeamRecord record = c.elem();
MyOutputClass elem = new MyOutputClass();
//get field value by name
elem.SalesComponent = record.getString("CPS_H...");
// get another field value by name
elem.DuetoValue = record.getInteger("...");
...
c.output(elem);
}
})
);
您可以通过添加一个简单的ParDo
来验证这样的内容,您可以在其中放置断点并查看调试器中的元素,或者将元素输出到其他位置(例如控制台)。
答案 1 :(得分:0)
我能够使用以下方法解决此问题:
PCollection<MyOutputClass> final_out = record40.apply(ParDo.of(new DoFn<BeamRecord, MyOutputClass>() {
private static final long serialVersionUID = 1L;
@ProcessElement
public void processElement(ProcessContext c) throws ParseException {
BeamRecord record = c.element();
String strArr = record.toString();
String strArr1 = strArr.substring(24);
String xyz = strArr1.replace("]","");
String[] strArr2 = xyz.split(",");