我正在使用Beam SQL做一些实验。
我从转换PCollection<Row>
中获得了SampleSource
,并将其输出传递给SqlTransform
。
String sql1 = "select c1, c2, c3 from PCOLLECTION where c1 > 1";
下面的代码运行没有任何错误。
POutput it = p.apply(new SampleSource()).apply(SqlTransform.query(sql1));
p.run().waitUntilFinish();
但是,当我尝试以下代码行时,出现运行时错误。
POutput it = p.apply(new SampleSource());
it.getPipeline().apply(SqlTransform.query(sql1));
p.run().waitUntilFinish();
错误详细信息是
Caused by: org.apache.beam.repackaged.beam_sdks_java_extensions_sql.org.apache.calcite.sql.validate.SqlValidatorException: Object 'PCOLLECTION' not found
请提供一些提示。
答案 0 :(得分:1)
它不起作用,因为您是将SqlTransform
应用于管道,而不是PCollection
。
您可能希望按照以下方式进行更改:
// source probably returns a PCollection,
// would make sense to change 'it' to PCollection:
PCollection<...> it = p.apply(new SampleSource());
// then apply SqlTransform to the PCollection from the previous step,
// that is apply it directly to 'it':
it.apply(SqlTransform.query(sql1));
...
从较高的角度看,Beam管道的工作原理:
PTransform
,并生成从该来源读取的某些元素的PColelction
; PTransforms
链接到PCollection
上以处理数据(概念上,每个步骤都会产生不同的PCollections
); SqlTransform
是普通的PTransform
,预期将其应用于元素PCollection
并输出另一个PCollection
。您在SqlTransform.create()
中指定的查询将应用于PCollection
。它期望数据来自神奇的PCOLLECTION
表,该表代表您将PCollection
应用于的SqlTransform
。
您在示例中所做的是不同的:
PTransform
,该来源产生POutput
不一定是PCollection
; SqlTransform
; 因此,发生的情况是在这种情况下,SqlTransform
应用于管道的“根”,而不是源于源头的PCollection
。现在,您有两个PTransforms
彼此独立地应用于根,而不是依次应用PTransforms
的链。
另一个警告是SqlTransform
期望输入元素为Rows
,因为SQL作为一种语言仅适用于表示为行的数据。有两种方法可以实现此目的:
Rows
之间应用另一个ParDo
,将源产生的元素手动转换为SqlTransform
; Schema
框架(例如检出PCollection.setSchema()
方法),该框架允许Beam SQL自动将输入元素转换为Rows
;