Spark流:非结构化记录

时间:2018-10-10 07:20:26

标签: scala apache-spark spark-streaming databricks spark-structured-streaming

我们正在使用流媒体来消费 EventHub 中的数据。 传入流包含各种类型(大约400种不同类型)的 JSON 记录

每个记录将使用 ProductId 属性进行分类。

示例(记录的传入流):

record1 - { productId: 101, colA: "some-val", colB: "some-val" }
record2 - { productId: 104, colC: "some-val", colD: "some-val" }
record3 - { productId: 202, colA: "some-val", colD: "some-val", colF: "some-val" }
record3 - { productId: 342, colH: "some-val", colJ: "some-val", colK: "some-val" }

每条记录中的属性数各不相同,但是具有相似的 productId 的记录将具有完全相同的属性数。

ProductId的范围为(1-400),记录中的属性数最多为50。

我想阅读上面的JSON记录流并写到不同的镶木地板/三角洲位置,例如

    Location(Delta/Parquet)             Records
    -----------------------------------------------------------------
    /mnt/product-101        Contains all records with productId - 101
    /mnt/product-104        Contains all records with productId - 104
    /mnt/product-202        Contains all records with productId - 202
    /mnt/product-342        Contains all records with productId - 342

1)如何从包含不同记录类型的流中创建DataFrame / Dataset?

2)是否可以使用单个火花流并写入不同的增量/拼花位置?

1 个答案:

答案 0 :(得分:0)

请注意,使用此方法应该可以,但是会生成很多稀疏数据。

首先创建一个结合了所有列的StructType。

  val schema = new StructType().add("productId", LongType)
  .add("colA", StringType).add("colB", StringType)
  .add("colC", StringType)....

然后使用此架构和from_json函数创建流。

val df1 = df.select(from_json('value, schema).alias("tmp"))
.select("tmp.*")

最后使用partitionBy写入分区的实木复合地板文件。

val query1 = df1 
.writeStream 
.format("parquet") 
.option("path", "/mnt/product/") 
.option("checkpointLocation","/tmp/checkpoint")
.partitionBy("productId").start()

这将生成包含所有列的行。最初不在json输入中的列将被标记为null。 Parquet支持写入空值。但是最好先过滤一下。