给出BigQuery中的下表:
使用以下5个值:
一个简单的ParDo读取它,并打印出类型:
import com.google.api.services.bigquery.model.TableRow;
import com.google.cloud.dataflow.sdk.Pipeline;
import com.google.cloud.dataflow.sdk.io.BigQueryIO;
import com.google.cloud.dataflow.sdk.options.DataflowPipelineOptions;
import com.google.cloud.dataflow.sdk.options.DataflowPipelineWorkerPoolOptions;
import com.google.cloud.dataflow.sdk.options.PipelineOptionsFactory;
import com.google.cloud.dataflow.sdk.runners.BlockingDataflowPipelineRunner;
import com.google.cloud.dataflow.sdk.transforms.DoFn;
import com.google.cloud.dataflow.sdk.transforms.ParDo;
public class FloatBug {
public static void main(String[] args) {
DataflowPipelineOptions options = PipelineOptionsFactory.create().as(DataflowPipelineOptions.class);
options.setRunner(BlockingDataflowPipelineRunner.class);
options.setProject("<project_id>");
options.setWorkerMachineType("n1-standard-1");
options.setZone("us-central1-a");
options.setStagingLocation("<gcs_bucket>");
options.setNumWorkers(1);
options.setMaxNumWorkers(1);
options.setAutoscalingAlgorithm(DataflowPipelineWorkerPoolOptions.AutoscalingAlgorithmType.NONE);
Pipeline pipeline = Pipeline.create(options);
pipeline.apply(BigQueryIO.Read.from("FLOAT_BUG.float_bug")).apply(ParDo.of(new DoFn<TableRow, TableRow>() {
@Override
public void processElement(ProcessContext c) throws Exception {
Object o = c.element().get("VHH");
if (o instanceof Double) {
System.out.println("Awesome. Got expected Double: " + o);
} else if (o instanceof Integer) {
System.out.println("Bummer. Got an Integer: " + o);
} else {
assert false;
}
}
}));
pipeline.run();
}
}
在本地运行会为每个值返回一个Double。这就是我所期望的:
Awesome. Got expected Double: 2.0
Awesome. Got expected Double: 2.245
Awesome. Got expected Double: 1.773
Awesome. Got expected Double: 4.567
Awesome. Got expected Double: 1.342
但是,使用数据流服务在云中运行会为值Integer
返回2.0
:
Awesome. Got expected Double: 2.245
Awesome. Got expected Double: 1.342
Awesome. Got expected Double: 1.773
Awesome. Got expected Double: 4.567
Bummer. Got an Integer: 2
它应该返回Double
,而不是2.0 {/ p>的Integer
答案 0 :(得分:2)
观察是真的。从BigQuery读取输入的管道可以输出与BigQuery架构中的基础数据类型不同的类型的数据。如所观察到的,类型也可能因元素而异。
Dataflow Service首先将数据从BigQuery导出到Google Cloud Storage中的JSON编码文件,然后从这些文件中读取数据,这是一个令人遗憾的结果。显然,JSON不保留类型。例如,浮点数2.0
将被编码为字符串"2"
,在Java中将被读取为Integer
。使用DirectPipelineRunner
执行管道时不会发生这种情况,因为该运行器直接从BigQuery读取。
现在,避免这类问题的最简单方法是通过Java中的Number
抽象类。这是像Double
和Integer
这样的类的超类。将结果解释为Number
然后在其上调用doubleValue()
方法应该是安全的。
那说,前进,我希望这种行为能够改变。确切的时间线尚不清楚,但数据流服务的行为应该很快就会与本地执行相匹配。通过Number
类的解决方法应该是正确的。