【问题标题】:How to use a PCollection to build datastore query in a beam pipeline?如何使用 PCollection 在光束管道中构建数据存储查询?
【发布时间】:2020-03-19 00:35:27
【问题描述】:

我正在构建一个光束管道,以按照一些规则将 csv 文件处理/转换为 xml 文件。到目前为止,我的方法是在管道开始时按行拆分输入 csv 文件,并将每一行输入到管道中。在管道中,将每一行转换为一个 xml 标记,在管道结束时,我将全局上的所有内容合并到最终的 xml 文件中。现在的问题是我需要存储在 Google Datastore 中的一些额外信息来为 csv 文件中的每一行构建 xml 标记,我不知道该怎么做,因为从数据存储区检索数据的查询是运行时参数(https://beam.apache.org/releases/pydoc/2.16.0/apache_beam.io.gcp.datastore.v1new.datastoreio.html#apache_beam.io.gcp.datastore.v1new.datastoreio.ReadFromDatastore) 并且查询取决于 PCollection。我需要构建一个这样的查询:

Select from xxx where id in PCollection

有没有办法做到这一点?比如 combineGlobally 来构建查询,然后以某种方式将查询传递给 ReadFromDatastore 函数?或者有什么方法可以做我需要的吗?

我现在有这样的事情:

with beam.Pipeline(options=pipeline_options) as p:
    items = (
        p |
        'ReadCsvFile' >> beam.io.Read(CsvFileSource(input_name))
        'PrepareToJoin' >> beam.ParDo(PrepareToJoin())
    )

    datastore_items = (p |
        'DatastoreDataP' >> ReadFromDatastore(project_id, query)
    )

    new_items = (
        {'data': items, 'datastore': datastore_items} |
        'JoinWithDatastore' >> beam.CoGroupByKey() |
        'PostJoinProcess' >> beam.ParDo(PostJoinProcess())
    )

    xml_file = (new_items |
        'ItemToXmlTag' >> beam.ParDo(ItemToXmlTag()) |
        'MakeXMLFile' >> beam.CombineGlobally(XMLCombineFn()) |
        WriteToText(output_name)
    )

如您所见,查询是管道中的一个参数。

提前感谢您的帮助!

【问题讨论】:

    标签: python google-cloud-platform google-cloud-datastore apache-beam


    【解决方案1】:

    您可以使用 ParDo 来实现此目的。下面是如何编写 ParDo 的伪代码,其中您处理 PCollection 的每个元素,然后进行 DataStore 查找

    
    class EnrichEntities(beam.DoFn):
    """Updates Datastore entity"""
    def process(self, element):
        key = client.key('Task', 'sample_task')
        task = client.get(element.key)
    
            return [element]
        else:
            return [element]
    

    然后在您的管道中,您可以使用 ParDo,如下所示

    with beam.Pipeline() as pipeline:
      results = (
          pipeline
          | 'Create inputs' >> beam.Create()
          | 'DoFn methods' >> beam.ParDo(EnrichEntities())
          | beam.Map(print)
    

    为了提高查找的性能,您还可以使用BagState,其中您可以一次查找 N 条记录。这是一个实现这个https://beam.apache.org/blog/2017/08/28/timely-processing.html的链接

    【讨论】:

    • 对不起,如果这个问题很愚蠢,但是对每个元素进行查找并不是低效的吗?如果不是,我应该在哪里初始化数据存储客户端?我可以在 EnrichEntities ParDo 函数的开头使用返回 datastore.Client(PROJECT_ID) 的函数吗?还是我应该在其他地方初始化客户端?提前感谢您的帮助。
    • 您可以从查找每个元素开始。您可以在start 方法中初始化客户端,以便针对每个 ParDo 实例初始化客户端。 process 方法处理集合中的每个元素。如果这个答案有帮助,请接受我的回答。
    • 大家好,我正在尝试这种确切的情况,但无法识别 Datastore 客户端的初始化...我需要在哪里初始化它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    相关资源
    最近更新 更多