如何在 Spark Scala 中进行类型安全数据集左连接

问题描述 投票:0回答:1

背景

人们对 Spark 的数据集 API 实际上并未提供完全类型安全的连接感到非常苦恼,但我很固执,所以我真的想尝试尽可能接近(不使用某些外部库)。

我可以通过内部连接做到这一点。但是,我有时想做左(或右)外连接,但不知道如何获得正确的类型签名。

问题

具体来说,

如果无论(左)外连接类型如何,此函数都不会在任一侧返回选项,如何使用

Dataset.joinWith(rightDS, condition, "left")

看起来要么需要在“外部”侧返回一个选项(如果进行左连接,则为右侧),或者根本不返回不可连接的行(即,将成为内部连接而不是真正的外部连接)。不知何故,当我将“外部”字段映射到我的合并表中时,我需要让它们为空,但是如果我将“外部”行作为选项进行模式匹配,它会阻止我。

scala apache-spark apache-spark-dataset
1个回答
3
投票

TL;博士

Spark 的数据集 API 为整个不可连接的“外部”记录返回 null。

...不是字段级别的 null(如 SQL),也不是您可以简单匹配的记录或字段级别的选项。

:( ....
简而言之,
joinWith
函数欺骗了类型签名,并随意返回一个无声的
null
,而不是规定的案例类(或类型)。

解决方案

  • 在类型签名和模式匹配中,表现得好像它将返回有效记录(例如,不要在 Option 中包装模式匹配,因为这与它们的类型签名不匹配)。
  • 但是,在实际使用该字段之前,请创建一个新的 val,将可能为空的“外部”记录包装在选项中。

示例

这应该是有效的 scala 代码(假设您已经设置了 Spark 上下文并定义了数据集和案例类),但我还没有测试过它。

val joinedDs = leftDs
  .joinWith(rightDs, leftDs("key_field") === rightDs("key_field"), "left")
  .map { x => {
    val l = x._1 // alias the left side
    val r = Option(x._2) // alias and Optionalize the right side
    ResultCaseClass( // defined elsewhere
      l.key_field,
      l.non_key_field, // may be an Option, or not - just as it appears in leftDs
      option_field = r.map(_.regular_field), // turns nonOption rightDS to Option
      reoption_field = r.flatMap(_.already_an_option) // flatten rightDs Option
    )
  }}
 
© www.soinside.com 2019 - 2024. All rights reserved.