python - 连接由主键链接的 2 个 JSON 输入

标签 python google-cloud-dataflow apache-beam

我正在尝试合并 2 个 JSON 输入(此示例来自文件,但稍后将来自 Google Pub Sub 输入):

orderID.json:    
{"orderID":"test1","orderPacked":"Yes","orderSubmitted":"Yes","orderVerified":"Yes","stage":1}



combined.json:
    {"barcode":"95590","name":"Ash","quantity":6,"orderID":"test1"}
    {"barcode":"95591","name":"Beat","quantity":6,"orderID":"test1"}
    {"barcode":"95592","name":"Cat","quantity":6,"orderID":"test1"}
    {"barcode":"95593","name":"Dog","quantity":6,"orderID":"test2"}
    {"barcode":"95594","name":"Scar","quantity":6,"orderID":"test2"}

像这样(使用 orderID 作为唯一主键):

output.json: 
{"orderID":"test1","orderPacked":"Yes","orderSubmitted":"Yes","orderVerified":"Yes","stage":1,"barcode":"95590","name":"Ash","quantity":6}
{"orderID":"test1","orderPacked":"Yes","orderSubmitted":"Yes","orderVerified":"Yes","stage":1,"barcode":"95591","name":"Beat","quantity":6}
{"orderID":"test1","orderPacked":"Yes","orderSubmitted":"Yes","orderVerified":"Yes","stage":1,"barcode":"95592","name":"Cat","quantity":6}

我现在有这样的代码,改编自 join two json in Google Cloud Platform with dataflow

from __future__ import absolute_import
import argparse
import apache_beam as beam
import json
from apache_beam.options.pipeline_options import PipelineOptions
from apache_beam.options.pipeline_options import SetupOptions
from apache_beam.options.pipeline_options import StandardOptions
from google.api_core import datetime_helpers
from google.api_core.exceptions import InternalServerError
from google.api_core.exceptions import ServiceUnavailable
from google.api_core.exceptions import TooManyRequests
from google.cloud import bigquery

def run(argv=None):
    """Build and run the pipeline."""
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--topic',
        type=str,
        help='Pub/Sub topic to read from')
    parser.add_argument(
        '--topic2',
        type=str,
        help='Pub/Sub topic to match with'
    )
    parser.add_argument(
        '--output',
        help=('Output local filename'))

    args, pipeline_args = parser.parse_known_args(argv)
    options = PipelineOptions(pipeline_args)
    options.view_as(SetupOptions).save_main_session = True
    options.view_as(StandardOptions).streaming = True

p = beam.Pipeline(options=options)

    orderID = (p | 'read from text1' >> beam.io.ReadFromText('orderID.json') 
    #'Read from orderID PubSub' >> beam.io.ReadFromPubSub(topic=args.topic2)
                | 'Parse JSON to Dict' >> beam.Map(lambda e: json.loads(e))
                | 'key_orderID' >> beam.Map(lambda orders: (orders['orderID'], orders))
                )

    orders_si = beam.pvalue.AsDict(orderID) 

    orderDetails = (p | 'read from text' >> beam.io.ReadFromText('combined.json') 
                      | 'Parse JSON to Dict1' >> beam.Map(lambda e: json.loads(e)))
    #'Read from PubSub' >> beam.io.ReadFromPubSub(topic=args.topic))

    def join_orderID_orderDetails(order, order_dict):
        return order.update(order_dict[order['orderID']])

    joined_dicts = orderDetails | beam.Map(join_orderID_orderDetails, order_dict=orders_si)

    joined_dicts | beam.io.WriteToText('beam.output')

p.run()
#result.wait_until_finish()

if __name__ == '__main__':
    run()

但是我现在在 beam.output 中的输出仅显示:

None
None
None

有人可以向我指出我做错了什么吗?

与报告的重复帖子不同的问题是:

  1. 为什么我的结果是“无”?
  2. 我在这里做错了什么?
  3. 我怀疑这些是问题所在:

    • “order”变量 - 是否在“join_orderID_orderDetails”中正确引用
    • 在“join_dicts”中列出项目“join_orderID_orderDetails”? - 引用也正确吗?

最佳答案

尝试以下方法,希望对您有所帮助。

这里我使用了您的订单数组并组合,而不是使用文件。

order = [{"orderID":"test1","orderPacked":"Yes","orderSubmitted":"Yes","orderVerified":"Yes","stage":1}]

combined = [
   {"barcode":"95590","name":"Ash","quantity":6,"orderID":"test1"},
   {"barcode":"95591","name":"Beat","quantity":6,"orderID":"test1"},
   {"barcode":"95592","name":"Cat","quantity":6,"orderID":"test1"},
   {"barcode":"95593","name":"Dog","quantity":6,"orderID":"test2"},
   {"barcode":"95594","name":"Scar","quantity":6,"orderID":"test2"}
   ]


def joinjson(repl, tobeCombined):
  newarr = []
  for data in tobeCombined:
    replData = getOrderData(repl,data['orderID'])
    if replData is not None:
      data.update(replData)
    newarr.append(data)

  return newarr

def getOrderData(order, orderID):
  for data in order:
    print("Data OrderID : ",data['orderID'])
    if data['orderID'] == orderID:
      return data



print(joinjson(order,combined))

关于python - 连接由主键链接的 2 个 JSON 输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57387749/

相关文章:

python - 在 scipy 最小化期间​​打印当前评估的参数

java - 如何在 Apache Beam 中为我的 PCollection 使用 AutoValue 数据类型?

python - Apache Beam 本地 Python 依赖项

谷歌云数据流卡住重复错误 'Error syncing pod...failed to "StartContainer"for "sdk"with CrashLoopBackOff'

java - 从 Kubernetes 运行梁数据流作业

python - 重命名 Django 模型中的默认 id 列

python - 在 Windows 10 上为 PyPy3 安装 numpy 时出现问题

python - 如何从 Google Dataflow 中的 PCollection 中获取元素列表并在管道中使用它来循环写入转换?

python - 如何在 Sharepoint 中更新文档的元数据? (Linux -> Web 服务 -> Sharepoint)

google-bigquery - 将数据流式传输到 Bigquery 与将数据上传到 PubSub 然后使用数据流将数据插入到 Bigquery 之间的优缺点是什么