Google cloud dataflow 在Apache Beam中将Side输入应用于BigQueryIO.read操作

Google cloud dataflow 在Apache Beam中将Side输入应用于BigQueryIO.read操作,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,有没有一种方法可以在ApacheBeam中将side输入应用于BigQueryIO.read()操作 例如,假设我在PCollection中有一个值,我想在查询中使用该值从BigQuery表中获取数据。这是否可以使用侧面输入?还是应该在这种情况下使用其他方法 我在类似的情况下使用了NestedValueProvider,但我想只有当某个值取决于我的运行时值时,我们才能使用它。或者我可以在这里用同样的东西吗?如果我错了,请纠正我 我尝试的代码: Bigquery bigQueryClient =

有没有一种方法可以在ApacheBeam中将side输入应用于BigQueryIO.read()操作

例如,假设我在PCollection中有一个值,我想在查询中使用该值从BigQuery表中获取数据。这是否可以使用侧面输入?还是应该在这种情况下使用其他方法

我在类似的情况下使用了NestedValueProvider,但我想只有当某个值取决于我的运行时值时,我们才能使用它。或者我可以在这里用同样的东西吗?如果我错了,请纠正我

我尝试的代码:

Bigquery bigQueryClient = start_pipeline.newBigQueryClient(options.as(BigQueryOptions.class)).build();
    Tabledata tableRequest = bigQueryClient.tabledata();

PCollection<TableRow> existingData = readData.apply("Read existing data",ParDo.of(new DoFn<String,TableRow>(){
    @ProcessElement
    public void processElement(ProcessContext c) throws IOException
    {
        List<TableRow> list = c.sideInput(bqDataView);
        String tableName = list.get(0).get("table").toString();
        TableDataList table = tableRequest.list("projectID","DatasetID",tableName).execute();

        for(TableRow row:table.getRows())
        {
            c.output(row);
        }
    }
    }).withSideInputs(bqDataView));
Bigquery bigQueryClient=start_pipeline.newBigQueryClient(options.as(BigQueryOptions.class)).build();
Tabledata tableRequest=bigQueryClient.Tabledata();
PCollection existingData=readData.apply(“读取现有数据”),ParDo.of(new DoFn(){
@过程元素
public void processElement(ProcessContext c)引发IOException
{
列表=c.sideInput(bqDataView);
字符串tableName=list.get(0.get(“表”).toString();
TableDataList table=tableRequest.list(“projectID”、“DatasetID”、tableName).execute();
for(TableRow行:table.getRows())
{
c、 输出(行);
}
}
}).使用SideInputs(bqDataView));
我得到的错误是:

Exception in thread "main" java.lang.IllegalArgumentException: unable to serialize BeamTest.StarterPipeline$1@86b455
    at org.apache.beam.sdk.util.SerializableUtils.serializeToByteArray(SerializableUtils.java:53)
    at org.apache.beam.sdk.util.SerializableUtils.clone(SerializableUtils.java:90)
    at org.apache.beam.sdk.transforms.ParDo$SingleOutput.<init>(ParDo.java:569)
    at org.apache.beam.sdk.transforms.ParDo.of(ParDo.java:434)
    at BeamTest.StarterPipeline.main(StarterPipeline.java:158)
Caused by: java.io.NotSerializableException: com.google.api.services.bigquery.Bigquery$Tabledata
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at org.apache.beam.sdk.util.SerializableUtils.serializeToByteArray(SerializableUtils.java:49)
    ... 4 more
线程“main”java.lang.IllegalArgumentException中的异常:无法序列化BeamTest.StarterPipeline$1@86b455 位于org.apache.beam.sdk.util.SerializableUtils.SerializationToByteArray(SerializableUtils.java:53) 位于org.apache.beam.sdk.util.SerializableUtils.clone(SerializableUtils.java:90) 位于org.apache.beam.sdk.transforms.ParDo$SingleOutput.(ParDo.java:569) 位于org.apache.beam.sdk.transforms.ParDo.of(ParDo.java:434) 位于BeamTest.StarterPipeline.main(StarterPipeline.java:158) 原因:java.io.NotSerializableException:com.google.api.services.bigquery.bigquery$Tabledata 位于java.io.ObjectOutputStream.WriteObject 0(未知源) 位于java.io.ObjectOutputStream.defaultWriteFields(未知源) 位于java.io.ObjectOutputStream.writeSerialData(未知源) 位于java.io.ObjectOutputStream.writeOrdinaryObject(未知源) 位于java.io.ObjectOutputStream.WriteObject 0(未知源) 位于java.io.ObjectOutputStream.writeObject(未知源) 位于org.apache.beam.sdk.util.SerializableUtils.SerializationToByteArray(SerializableUtils.java:49) ... 4更多
梁模型目前不太支持这种依赖数据的操作

一种方法是编写自己的
DoFn
,它接收侧面输入并直接连接到BQ。不幸的是,这不会给您任何并行性,因为
DoFn
将完全在同一个线程上运行

一旦可拆分的
DoFn
s在梁中得到支撑,这将是一个不同的故事


在当前的情况下,您需要使用添加查询BQ的代码,就像您不在Beam管道中一样

根据您问题中的代码,关于如何实现这一点的大致思路如下:

class ReadDataDoFn extends DoFn<String,TableRow>(){
    private Tabledata tableRequest;

    private Bigquery bigQueryClient;

    private Bigquery createBigQueryClientWithinDoFn() {
        // I'm not sure how you'd implement this, but you had the right idea
    }

    @Setup
    public void setup() {
        bigQueryClient = createBigQueryClientWithinDoFn(); 
        tableRequest = bigQueryClient.tabledata();
    }
    @ProcessElement
    public void processElement(ProcessContext c) throws IOException
    {
        List<TableRow> list = c.sideInput(bqDataView);
        String tableName = list.get(0).get("table").toString();
        TableDataList table = tableRequest.list("projectID","DatasetID",tableName).execute();

        for(TableRow row:table.getRows())
        {
            c.output(row);
        }
    }
}

PCollection<TableRow> existingData = readData.apply("Read existing data",ParDo.of(new ReadDataDoFn()));
类ReadDataDoFn扩展了DoFn(){ 私有表数据表请求; 私有Bigquery bigQueryClient; 私有Bigquery createBigQueryClientWithinDoFn(){ //我不知道你会如何实施,但你的想法是对的 } @设置 公共作废设置(){ bigQueryClient=CreateBigQueryClient WithIndofn(); tableRequest=bigQueryClient.tabledata(); } @过程元素 public void processElement(ProcessContext c)引发IOException { 列表=c.sideInput(bqDataView); 字符串tableName=list.get(0.get(“表”).toString(); TableDataList table=tableRequest.list(“projectID”、“DatasetID”、tableName).execute(); for(TableRow行:table.getRows()) { c、 输出(行); } } } PCollection existingData=readData.apply(“读取现有数据”,ParDo.of(new ReadDataDoFn()));
ok@pablo。请提供一个将DoFn连接到BigQuery的示例。我的回答是,您需要使用BQ客户机库()添加查询BQ的代码,就像您不在Beam管道中一样。这有意义吗?是的…我试试看。谢谢@pabloI,我已经用我尝试过的代码更新了帖子。但是我得到一个错误,说“无法序列化”。这种方法行吗?您的想法是对的,但是您需要从辅助进程内部连接到bigquery,而不是在管道创建时。我更新了我的答案以反映这一点。另外,请注意,这是使用Beam的一种非常尴尬的形式,但它是目前提供您所寻找的功能的唯一方法。