Google bigquery 如何在数据流中从PCollection读取bigQuery

Google bigquery 如何在数据流中从PCollection读取bigQuery,google-bigquery,google-cloud-dataflow,apache-beam,Google Bigquery,Google Cloud Dataflow,Apache Beam,我有一个从pubsub获得的对象的PCollection,比如说: PCollection<Student> pStudent ; PCollection pStudent; 在学生属性中,有一个属性,比如说studentID; 我想用这个学生id从BigQuery中读取属性(class_代码),并在PCollection中将我从BQ获得的class_代码设置为student对象 有人知道如何实现这一点吗? 我知道在beam中有一个BigQueryIO,但是如果我想在BQ中执行

我有一个从pubsub获得的对象的PCollection,比如说:

 PCollection<Student> pStudent ;
PCollection pStudent;
在学生属性中,有一个属性,比如说studentID; 我想用这个学生id从BigQuery中读取属性(class_代码),并在PCollection中将我从BQ获得的class_代码设置为student对象

有人知道如何实现这一点吗?
我知道在beam中有一个
BigQueryIO
,但是如果我想在BQ中执行的查询字符串条件来自PCollection中的student对象(studentID),我如何从BigQuery的结果中将值设置为PCollection?我考虑了两个选项来实现这一点。一种方法是使用
BigQueryIO
读取整个表并将其具体化为一个侧输入,或者使用
CoGroupByKey
连接所有数据。另一种可能性,我在这里实现的,是直接使用Java客户机库

我使用以下方法创建了一些虚拟数据:

$bq mk test.学生姓名:STRING,年级:STRING
$bq query——使用_legacy_sql=false'插入test.students(姓名、年级)值(“Yoda”、“A+”)、(“Leia”、“B+”)、(“Luke”、“C-”)、(“Chewbacca”、“F”)'
看起来是这样的:

然后,在管道中,我生成一些输入虚拟数据:

对于这些“学生”中的每一个,我都按照中的方法在BigQuery表中获取相应的分数。根据您的数据量、费率(配额)和成本考虑因素,按照前面的评论进行考虑。完整示例:

公共类动态查询{
私有静态最终记录器LOG=LoggerFactory.getLogger(dynamicquerys.class);
@抑制警告(“串行”)
公共静态void main(字符串[]args){
PipelineOptions=PipelineOptionsFactory.fromArgs(args.create();
Pipeline p=Pipeline.create(选项);
//创建输入虚拟数据
PCollection students=p.apply(“读取学生数据”,创建(“卢克”、“莱娅”、“尤达”、“丘巴卡”)。使用编码器(StringUtf8Coder.of());
//ParDo将每个学生与BigQuery中的成绩进行映射
PCollection marks=students.apply(“从BigQuery中读取分数”),ParDo.of(new DoFn(){
@过程元素
public void processElement(ProcessContext c)引发异常{
BigQuery BigQuery=BigQueryOptions.getDefaultInstance().getService();
QueryJobConfiguration查询配置=
QueryJobConfiguration.newBuilder(
选择名称、等级
+“来自'PROJECT\u ID.test.students'”
+“其中name=”
+“\”“+c.element()+”\”“//获取适当的学生
+“限额1”)
.setUseLegacySql(false)//对查询使用标准SQL语法。
.build();
//创建作业ID,以便我们可以安全地重试。
JobId JobId=JobId.of(UUID.randomUUID().toString());
Job queryJob=bigquery.create(JobInfo.newBuilder(queryConfig.setJobId(jobId.build());
//等待查询完成。
queryJob=queryJob.waitFor();
//检查错误
if(queryJob==null){
抛出新的RuntimeException(“作业不再存在”);
}else if(queryJob.getStatus().getError()!=null){
抛出新的RuntimeException(queryJob.getStatus().getError().toString());
}
//得到结果。
QueryResponse response=bigquery.getQueryResults(作业ID)
TableResult=queryJob.getQueryResults();
字符串标记=新字符串();
for(FieldValueList行:result.iterateAll()){
mark=row.get(“grade”).getStringValue();
}
c、 输出(千伏(c元件(),标记));
}
}));
//登录以检查一切是否正常
标记。应用(“记录结果”,第页,共页)(新DoFn(){
@过程元素
public void processElement(ProcessContext c)引发异常{
LOG.info(“元素:“+c.Element().getKey()+”+c.Element().getValue());
c、 输出(c.element());
}
}));
p、 run();
}
}
输出为:

2018年11月8日下午2:17:16 com.dataflow.samples.dynamicquerys$2 processElement
信息:元素:尤达A+
2018年11月8日下午2:17:16 com.dataflow.samples.dynamicquerys$2 processElement
信息:元素:卢克C-
2018年11月8日下午2:17:16 com.dataflow.samples.dynamicquerys$2 processElement
信息:元素:丘巴卡F
2018年11月8日下午2:17:16 com.dataflow.samples.dynamicquerys$2 processElement
信息:元素:Leia B+

(使用BigQuery 1.22.0和2.5.0 Java SDK for Dataflow进行测试)

您不希望将BigQuery用于此用例,因为BigQuery不是OLTP数据库,并且此用例似乎需要数据库中的事务属性。当然,您可以获取BigQuery表作为数据流的映射表,但数据要么保持不变,要么您将多次查询BigQuery,这可能会使您付出不必要的代价。如果您想使用GCP中的内容来实现此目的,请使用云SQL或云数据存储。
Create.of("Luke", "Leia", "Yoda", "Chewbacca")