【问题标题】:How to put nested JSON data into BigQuery table with Google Cloud Platform's dataflow's Pub/Sub Topic -> BigQuery Template如何使用 Google Cloud Platform 的数据流的 Pub/Sub 主题 -> BigQuery 模板将嵌套的 JSON 数据放入 BigQuery 表
【发布时间】:2021-09-10 19:45:51
【问题描述】:

我正在尝试将 IoT 设备发送的消息存储在 BigQuery 表中。

云架构如下:

本地设备 -> json_message -> mqtt_client -> GC IoT 设备 -> 设备注册表 -> Pub/Sub 主题 -> 带有 Pub/Sub 主题到 BigQuery 模板的数据流 -> BigQuery 表

我已经让这个系统使用这样构造的非嵌套 JSON 消息

json_dict = {"instrument": instrument,
 "spectrum": str(self.spectrum),
 "spectrum_creation_time": self.creation_dt.timestamp(),
 "messenger_creation_time": time.time()}

return json.dumps(json_dict)

BigQuery 中成功存储此数据的表具有以下架构:

   Last modified                  Schema                 Total Rows   Total Bytes   Expiration   Time Partitioning   Clustered Fields   Labels
 ----------------- ------------------------------------ ------------ ------------- ------------ ------------------- ------------------ --------
  04 Sep 00:24:22   |- instrument: string                1277         81897474
                    |- spectrum: string
                    |- spectrum_creation_time: string
                    |- messenger_creation_time: string

现在我试图让这个系统使用嵌套的 JSON 消息,它的构造如下:

json_dict = {'timestamp': 'AUTO',
             'values': [
                        {'id': instrument + '.Time',
                         'v': time.time(),
                         't': time.time()},
                        {'id': instrument + 'Intensity',
                         'v': str(self.spectrum),
                         't': self.creation_dt.timestamp()}
                        ]}

return json.dumps(json_dict)

我正在尝试将其存储在具有以下架构的 BigQuery 表中:

   Last modified               Schema              Total Rows   Total Bytes   Expiration   Time Partitioning   Clustered Fields   Labels
 ----------------- ------------------------------ ------------ ------------- ------------ ------------------- ------------------ --------
  09 Sep 23:56:20   |- timestamp: timestamp        0            0
                    +- values: record (repeated)
                    |  +- time: record
                    |  |  |- id: string
                    |  |  |- v: string
                    |  |  |- t: timestamp
                    |  +- spectrum: record
                    |  |  |- id: string
                    |  |  |- v: string
                    |  |  |- t: timestamp

不幸的是,当我尝试这种方法时,我收到以下错误,该错误由 DataFlow 输出到 BigQuery 中的错误表。

{"errors":[{"debugInfo":"","location":"values[0].v","message":"no such field: v.","reason":"invalid"}],"index":0}
null

解决此问题的最佳方法是什么?我无法更改嵌套的 JSON 结构,因为我正在构建一个测试套件,这是必需的格式。

【问题讨论】:

  • 我认为至少有两个可能的问题。 First time.time() 序列化为 json 作为第一个值的数字。其次,我认为您的架构似乎与结构层次结构不匹配,您似乎需要“时间”和“频谱”的键来匹配层次结构。您提到结构不可更改,但我不认为 bigquery 可以在没有键的情况下进行您需要的推理类型。
  • @Miach Kornfield 我一直假设 json 中元素的类型无关紧要,因为 json.dumps 函数将所有内容都转换为字符串。也许这个假设是不正确的。 str 是时间戳的首选数据类型吗?我同意架构似乎与结构层次结构不完全匹配。我想创建一个完全匹配的 BigQuery 架构是不可能的。如果这是真的,我将需要尝试另一种完全不同的方法。
  • 鉴于未嵌套列的工作,bq 在解析 JSON 时可能会宽松。鉴于您拥有的架构,修改结构或修改架构似乎有很大的灵活性。鉴于嵌套的 JSON,我认为“值”repeated<struct<id: string, v: string, t: timestamp>(带有额外的时间和频谱字段)将是最接近的模式,但从问题的细节中很难分辨
  • 谢谢!以下架构时间戳,重复 有效!

标签: json google-cloud-platform google-bigquery iot google-dataflow


【解决方案1】:

在@Miach Kornfield 的帮助下,我能够解决我的问题,他对我的原始问题发表了评论。这是我的解决方案。

我发送到 GCP 的 JSON 数据看起来像

json_dict = {"timestamp": "1631554378.2955232",
             'values': [
                        {"id":"testA.Time",
                         "v": "1631554378.2955232",
                         "t": "1631554378.2955232"},
                        {"id": "testA.Time.Intensity",
                         "v": "[1, 43, 4..]",
                         't': "1631554378.2955232"}
                         ]
            }

我的 bigquery 表的原始架构是

Original schema for bigquery

或文本形式

            Schema
------------------------------
 |- timestamp: timestamp
 +- values: record (repeated)
 |  +- time: record
 |  |  |- id: string
 |  |  |- v: string
 |  |  |- t: timestamp
 |  +- spectrum: record
 |  |  |- id: string
 |  |  |- v: string
 |  |  |- t: timestamp

有效的架构是

schema that worked

或文本形式

            Schema
------------------------------
 |- timestamp: timestamp
 +- values: record (repeated)
 |  |- id: string
 |  |- v: string
 |  |- t: timestamp

通过指示值的类型是记录(重复),这意味着它是一个结构数组,结构的结构由子列指定。细节(结构的结构由子列指定)对我来说并不明显,以及为什么我在解决这个问题时遇到了这么多麻烦。我不确定是否可以使用异构模式记录(重复)。

【讨论】:

    猜你喜欢
    • 2019-10-03
    • 2019-02-22
    • 2021-11-23
    • 2019-08-18
    • 2021-04-26
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 2017-05-10
    相关资源
    最近更新 更多