应用不适用于使用Apache Beam的ParDo和DoFn

时间:2018-11-08 15:58:27

标签: google-cloud-dataflow apache-beam

我正在实现Pub / Sub到BigQuery管道。它看起来类似于How to create read transform using ParDo and DoFn in Apache Beam,但在这里,我已经创建了一个PCollection。

我正在遵循Apache Beam documentation中描述的内容,以执行ParDo操作以使用以下管道来准备表行:

static class convertToTableRowFn extends DoFn<PubsubMessage, TableRow> {
    @ProcessElement
    public void processElement(ProcessContext c) {
        PubsubMessage message = c.element();
        // Retrieve data from message
        String rawData = message.getData();
        Instant timestamp = new Instant(new Date());
        // Prepare TableRow
        TableRow row = new TableRow().set("message", rawData).set("ts_reception", timestamp);
        c.output(row);
    }
}

// Read input from Pub/Sub
pipeline.apply("Read from Pub/Sub",PubsubIO.readMessagesWithAttributes().fromTopic(topicPath))
        .apply("Prepare raw data for insertion", ParDo.of(new convertToTableRowFn()))
        .apply("Insert in Big Query", BigQueryIO.writeTableRows().to(BQTable));

我在gist中找到了DoFn函数。

我一直收到以下错误:

The method apply(String, PTransform<? super PCollection<PubsubMessage>,OutputT>) in the type PCollection<PubsubMessage> is not applicable for the arguments (String, ParDo.SingleOutput<PubsubMessage,TableRow>)

我一直都知道ParDo / DoFn操作是逐元素的PTransform操作,对吗?我从来没有在Python中遇到过此类错误,所以对于为什么会发生这种情况我有些困惑。

1 个答案:

答案 0 :(得分:3)

您是对的,ParDos是逐元素的变换,您的方法看起来正确。

您看到的是编译错误。当Java编译器推断的apply()方法的参数类型与实际输入的类型不匹配时,例如会发生这种情况。 convertToTableRowFn

从错误中您会看到,它看起来像Java推断apply()的第二个参数的类型为PTransform<? super PCollection<PubsubMessage>,OutputT>,而您传递的是ParDo.SingleOutput<PubsubMessage,TableRow>的子类(您的convertToTableRowFn)。查看SingleOutput的定义,您的convertToTableRowFn基本上就是PTransform<PCollection<? extends PubsubMessage>, PCollection<TableRow>>。而且Java无法在期望apply的{​​{1}}中使用它。

看起来可疑的是Java没有将PTransform<? super PCollection<PubsubMessage>,OutputT>推断为OutputT。如果您有其他错误,将无法执行此操作的原因之一。您确定也没有其他错误吗?

例如,查看PCollection<TableRow>时您正在调用convertToTableRowFn,当我尝试执行该操作时它不存在,并且在那里编译失败。就我而言,我需要执行以下操作:message.getData()。另外rawData = new String(message.getPayload(), Charset.defaultCharset())期望一个字符串(例如代表BQ表名的字符串)作为参数,并且您传递了一些未知符号.to(BQTable))(虽然它存在于您的程序中,但这不是一个问题)。

修复了这两个错误后,您的代码将为我编译,BQTable被完全推断出并且类型兼容。