簡體   English   中英

使用 Spark Structured Streaming (pyspark) 從 Kafka Connect JSONConverter 消息中提取“有效載荷”(模式和有效載荷)

[英]Extracting "payload" from Kafka Connect JSONConverter messages with (schema & payload) using Spark Structured Streaming (pyspark)

然而,我想要完成的正是這個問題( 這里)的內容; 就我而言,我使用的是 Python/Pyspark 而不是 Scala。

我正在嘗試提取也包含架構的 Kafka 連接消息的“有效負載”部分。

示例消息:

{"schema":{"type":"struct","name":"emp_table","fields":[{"field":"emp_id","type":"string"},{"field":"emp_name","type":"String"},{"field":"city","type":"string"},{"field":"emp_sal","type":"string"},{"field":"manager_name","type":"string"}]},"payload":{"emp_id":"1","emp_name":"abc","city":"NYK","emp_sal":"100000","manager_name":"xyz"}}

第 1 步 - 為“有效負載”部分定義架構:

payload_schema = StructType([
StructField("emp_id", StringType(), False),
StructField("emp_name", StringType(), True),
StructField("city", StringType(), True),
StructField("emp_sal", StringType(), True),
StructField("manager_name", StringType(), True)])

第 2 步 - 從 Kafka 讀取:

df =spark.readStream.format("kafka")

第 3 步 - 從 Kafka 消息中獲取消息值:

kafka_df = df.selectExpr("CAST(value AS STRING)")

第 4 步 - 僅提取“有效載荷”(我被困在這里):

    import pyspark.sql.functions as psf

    emp_df = kafka_df\
    .select(psf.from_json(psf.col('value'), payload_schema).alias("DF"))\
    .select("DF.*")

我被困在這部分,因為我無法弄清楚如何在將它傳遞給 from_json() function 之前從 JSON 字符串中提取有效載荷。

注意:我知道我需要為整個消息定義完整的模式,然后才能在 from_json() 中使用它;但是; 我試圖只獲取“有效負載”json 字符串部分。

您可以使用 SQL function get_json_object

import pyspark.sql.functions as psf

kafka_df
  .select(psf.get_json_object(kafka_df['value'],"$.payload").alias('payload'))
  .select(psf.from_json(psf.col('payload'), payload_schema).alias("DF"))
  .select("DF.*")

或者,您需要先為整個消息定義完整模式,然后才能在from_json中使用它。

這意味着您的模式應該如下所示:

full_schema = StructType([
  StructField("schema", StructType([
    StructField("type", StringType(), False),
    StructField("name", StringType(), False),
    StructField("fields", StructType([
      StructField("field", StringType(), False),
      StructField("type", StringType(), False)
    ]),
  StructField("payload", StructType([
    StructField("emp_id", StringType(), False),
    StructField("emp_name", StringType(), True),
    StructField("city", StringType(), True),
    StructField("emp_sal", StringType(), True),
    StructField("manager_name", StringType(), True)
  ])
])

請仔細檢查此模式定義,因為我不完全確定如何在 Python 中的模式中定義數組,但我希望這個想法很清楚。

完成后,您可以通過 select 有效負載字段

import pyspark.sql.functions as psf

    emp_df = kafka_df\
    .select(psf.from_json(psf.col('value'), full_schema).alias("DF"))\
    .select("DF.payload.*")

假設您手頭沒有schema ,您可以這樣做:

import json

df = kafka_df.select(psf.get_json_object(kafka_df.value, "$.payload").alias("payload"))
final_df = df.rdd.map(lambda row: json.loads(row[0])).toDF().show()

出於某種原因,我錯過了 pyspark 有 get_json_object() function。在 Mike 的評論之后,我回到了文檔,我找到了我要找的東西。

答案如下:

    kafka_df = df.selectExpr("CAST(value AS STRING)")
    payload_df = kafka_df.select(psf.get_json_object(kafka_df.value, "$.payload").alias("payload"))
    emp_df = payload_df.select(psf.from_json(psf.col('payload'), schema).alias("DF")).select("DF.*")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM