Python 从Bigquery中读取几行作为辅助输入,但没有得到任何结果

Python 从Bigquery中读取几行作为辅助输入,但没有得到任何结果,python,python-2.7,google-bigquery,google-cloud-dataflow,apache-beam,Python,Python 2.7,Google Bigquery,Google Cloud Dataflow,Apache Beam,我在数据流管道的边输入方面遇到了问题,特别是BQ,即使在上了coursera并查看了样本之后 现在,我有一个管道,它读取gcs存储桶中的文件,获取它们的文件名,然后转换文件并将给定数量的行写入bigquery。我试图找出如何将文件名映射到来自bq的特定“键” 根据结果,我构建了所有文件名(filename1、filename2…)的元组,并动态创建一个查询,即: Bqquery=“从'project:dataset.table'where FILENAME IN(FILENAME tuple)'

我在数据流管道的边输入方面遇到了问题,特别是BQ,即使在上了coursera并查看了样本之后

现在,我有一个管道,它读取gcs存储桶中的文件,获取它们的文件名,然后转换文件并将给定数量的行写入bigquery。我试图找出如何将文件名映射到来自bq的特定“键”

根据结果,我构建了所有文件名(filename1、filename2…)的元组,并动态创建一个查询,即:
Bqquery=“从'project:dataset.table'where FILENAME IN(FILENAME tuple)'中选择文件名、文件ID”
我想我会这样做,因为一次大约有20个文件,所以从bq获取一次数据是有意义的,而不必在for循环中获取文件ID

所以我做了

Bqcollection = p | 'Get File_Id' >> beam.io.Read(beam.io.BigQuerySource(query=bqquery))
But the result I get is none 


for i in range(len(result)):
    current_file = result[i].path
    #query inside for loop 
    #bqquery= "SELECT FILE_ID" from 'project:dataset.table' where FILENAME = '{0}'".format(current_file)
   # file_id = p | 'GetFile_id_{0}'.format(i) >> beam.io.Read(beam.io.BigQuerySource(query=bqquery))
    globals()[variables[i]] = p | read_labels[i] >> ReadFromText(result[i].path) | add_filename_labels[i] >> beam.ParDo(AddFilenamesFn(), current_file)
我还尝试在for循环中进行查询,一次只获取一个文件名(请参阅注释掉的代码),但这也不起作用。最后,我要做的是将
beam.Pardo(AddFilenamesFn(),current_file)
更改为
beam.Pardo(AddFilenamesFn(),file_id)
,因此我不添加实际的文件名,而是添加文件id

[注意代码中提到的标签(即read_标签[i])只是数据流的标签]


我假设我缺少一些关于pcollections的基本信息,但不确定

考虑到前面的代码,我认为最简单的解决方案是在for循环中的
AddFilenamesFn
ParDo中运行查询。请记住,
beam.io.Read(beam.io.BigQuerySource(query=bqquery))
用于将行作为源读取,而不是在中间步骤中读取。因此,在我建议的情况下,您可以直接使用Python客户端库(
google cloud bigquery>0.27.0
):

class AddFilenamesFn(beam.DoFn):
“”“ParDo输出文件id(从BigQuery检索)和行为的dict”“”
def过程(自身、元素、文件路径):
从google.cloud导入bigquery
client=bigquery.client()
文件名=文件路径。拆分(“/”[-1]
query\u job=client.query(“”)
选择文件\u ID
从test.file\u映射
其中FILENAME='{0}'
限制1”“。格式(文件名))
结果=查询作业。结果()
对于结果中的行:
file\u id=row.file\u id
产生{'filename':文件\u id,'row':元素}
这将是实施的最直接的解决方案,但可能会出现问题。我们不是在管道开始时运行所有20个可能的查询,而是对每一行/记录运行一个查询。例如,如果一个文件中有3000个元素,那么相同的查询将启动3000次。但是,每个不同的查询实际上应该只运行一次,随后的查询“重复”将命中目标。还请注意,缓存的查询对交互式查询没有贡献

我使用了与我以前使用的相同的文件:

$gsutil类别gs://$BUCKET/countries1.csv
身份证,国家
1、瑞典
2、西班牙
gsutil类别gs://$BUCKET/countries2.csv
身份证,国家
3、意大利
4、法国
并添加了一个新表:

bq mk test.file\u映射文件名:STRING,file\u ID:STRING
bq查询--使用_legacy_sql=false'插入test.file_映射(文件名、文件ID)值(“countries1.csv”、“国家一号”)、(“countries2.csv”、“国家二号”)'

输出为:

INFO:root:{'filename':u'COUNTRIES ONE','row':u'id,country'}
信息:根:{'filename':u'COUNTRIES ONE','row':u'1,sweden'}
信息:根:{'filename':u'COUNTRIES ONE','row':u'2,spain'}
信息:根:{'filename':u'COUNTRIES TWO','row':u'id,country'}
信息:根:{'filename':u'COUNTRIES TWO','row':u'3,italy'}
信息:根:{'filename':u'COUNTRIES TWO','row':u'4,france'}
另一种解决方案是加载所有表,并使用
beam.io.BigQuerySource()
将其具体化为一个侧面输入(当然,这可能会有问题),或者,如您所说,将其分解为N个查询,并将每个查询保存到不同的侧面输入中。然后,您可以为每个记录选择适当的一个,并将其作为附加输入传递到
AddFilenamesFn
。试着写一本也很有趣

我提出的第一个解决方案的完整代码:

import argparse,日志记录
从操作员导入添加
将apache_梁作为梁导入
从apache_beam.options.pipeline_options导入PipelineOptions
从apache_beam.io导入ReadFromText
从apache_beam.io.filesystem导入文件元数据
从apache_beam.io.filesystem导入文件系统
从apache_beam.io.gcp.gcsfilesystem导入gcsfilesystem
GCSFileReader类:
“”“用于读取gcs文件的帮助器类”“”
定义初始(自我,地面军事系统):
self.gcs=gcs
类AddFilenamesFn(beam.DoFn):
“”“ParDo输出文件id(从BigQuery检索)和行为的dict”“”
def过程(自身、元素、文件路径):
从google.cloud导入bigquery
client=bigquery.client()
文件名=文件路径。拆分(“/”[-1]
query\u job=client.query(“”)
选择文件\u ID
从test.file\u映射
其中FILENAME='{0}'
限制1”“。格式(文件名))
结果=查询作业。结果()
对于结果中的行:
file\u id=row.file\u id
产生{'filename':文件\u id,'row':元素}
#只是记录输出以可视化结果
def write_res(元素):
logging.info(元素)
返回元素
def运行(argv=None):
parser=argparse.ArgumentParser()
已知参数,管道参数=解析器。解析已知参数(argv)
p=梁.管道(选项=管道选项(管道参数))
gcs=GCSFileSystem(管道选项(管道参数))
gcs_reader=GCSFileReader(gcs)
#就我而言,我正在寻找以“国家”开头的文件
BUCKET='BUCKET\u NAME'
结果=[m.metadata_在gcs.match中的m列表(['gs://{}/countries*'.格式(BUCKET)])]
物件
Bqcollection = p | 'Get File_Id' >> beam.io.Read(beam.io.BigQuerySource(query=bqquery))
But the result I get is none 


for i in range(len(result)):
    current_file = result[i].path
    #query inside for loop 
    #bqquery= "SELECT FILE_ID" from 'project:dataset.table' where FILENAME = '{0}'".format(current_file)
   # file_id = p | 'GetFile_id_{0}'.format(i) >> beam.io.Read(beam.io.BigQuerySource(query=bqquery))
    globals()[variables[i]] = p | read_labels[i] >> ReadFromText(result[i].path) | add_filename_labels[i] >> beam.ParDo(AddFilenamesFn(), current_file)