如何在 Spark 2.1 中创建可以具有可选属性的类型化数据集

Posted

技术标签:

【中文标题】如何在 Spark 2.1 中创建可以具有可选属性的类型化数据集【英文标题】:How to create typed dataset which can have optional attributes in Spark 2.1 【发布时间】:2017-05-16 06:12:01 【问题描述】:

我需要在 Spark 中使用数据集,它可以保存具有一些已知属性的实体,但也可以保存编译时属性的未知列表。我需要一种简单的方法来通过计算管道传递这些可选属性,而不是打扰它们。

编造代码示例:

> loaded.show
root
 |-- key: long (nullable = true)
 |-- value: string (nullable = true)
 |-- opt1: string (nullable = true)
 |-- opt2: long (nullable = true)   

让我们只想象我在编译时知道和关心的键和值。

case class BusinessEntity(key: Long, value: String) 
  def businessLogic = this

如果我将数据框转换为类型化数据集,额外的属性显然会丢失。

loaded.as[BusinessEntity].map(_.businessLogic).toDF.printSchema
root
 |-- key: long (nullable = true)
 |-- value: string (nullable = true)

我需要做的是将它们存储在实体中的某个位置,以便在计算管道的最后(可以包含连接等)我能够将它们提取到目标存储。

我可以想象使用以下一些方法来存储可选数据

case class BusinessEntity(key: String, value: String, extra: Row)
dataset.select("key", "value", "row.*")

case class BusinessEntity(key: String, value: String, extra: Map[String, AnyVal])
dataset.select($"key", $"value", 
/* Generate at runtime from attr list */ 
$"extra"("opt1").cast("long").as("opt2"), 
$"extra"("opt2").cast("long").as("opt2"))

case class BusinessEntity(key: String, value: String, extra: List[AnyVal])
dataset.select($"key", $"value", 
/* Generate at runtime from attr list */
$"extra"(0).cast("long").as("opt1"), 
$"extra"(1).cast("long").as("opt2"))

但它们都不起作用,因为 Spark 无法为 Row/Map[?, AnyVal]/List[AnyVal] 生成编码器。到目前为止,我只能考虑将可选属性存储为 JSON 编码的字符串,但我可以将其视为最后的手段;或使用 Encoders.kryo 为 AnyVal 的 Map 生成编码器。我是否遗漏了什么并且有更简单的方法来解决此类问题?

【问题讨论】:

【参考方案1】:

我只需将我的案例类中的可选值定义为Option 并将它们指定为None 作为默认值:

case class BusinessEntity(key: Long, value: String, opt1:Option[String]=None, opt2:Option[Long]=None) 

【讨论】:

以上是关于如何在 Spark 2.1 中创建可以具有可选属性的类型化数据集的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Serilog 输出模板中创建可选属性?

是否可以在 Swift 中创建具有 Self 或关联类型要求的通用计算属性,如果可以,如何?

使用具有常量值的 var 在 Spark DataFrame 中创建一个新列

如何使用 Swift 在 Firebase 中创建具有多个属性的用户?

Spark:如何在每个执行程序中创建本地数据帧

如何在 spark 2(java) 中创建广播变量?