如何为Option类型构造器创建编码器,例如Option[Int]?

3

是否可以在使用数据集API的情况下使用Option[_]成员,例如Option[Int]用于案例类?

我试图寻找一个例子,但尚未找到。这可能可以通过自定义编码器(映射?)来实现,但我还没有找到相关的示例。

使用Frameless库可能会实现这一点:https://github.com/adelbertc/frameless ,但应该有一种简单的方法可以使用基本Spark库完成。

更新

我正在使用:"org.apache.spark" %% "spark-core" % "1.6.1"

当尝试使用Option[Int]时,发生以下错误:

无法找到存储在Dataset中的类型的编码器。原始类型(Int、String等)和Product类型(案例类)通过导入sqlContext.implicits._支持,对于序列化其他类型的支持将在未来版本中添加。

解决方案更新

由于我只是在转换为数据集之前在函数内部声明了案例类(在我的情况下是在object Main {中),因此选项类型正常工作时,当我将案例类移到Main函数之外时。

2个回答

9
我们仅为我们支持的类型的子集在SQLImplicits中定义了implicit。我们可能应该考虑添加Option[T]用于常见的T,因为内部基础设施确实理解Option。您可以通过创建case class、使用Tuple构建所需的implicit来解决此问题(尽管这是使用内部API,因此可能会在未来的版本中被更改)。
implicit def optionalInt: org.apache.spark.sql.Encoder[Option[Int]] = org.apache.spark.sql.catalyst.encoders.ExpressionEncoder()

val ds = Seq(Some(1), None).toDS()

我发现了我所犯的错误,似乎 Scala 在函数内部和外部声明 case 类的方式不同。在 Main 函数之外声明 case 类,允许 as[_] 函数在没有任何额外 implicit 的情况下正常工作。我尝试使用你提到的 implicit,但无法使其正常工作(例如在函数内定义 case 类的情况下)。我的数据源是 MS SQL Server 数据库。 - Răzvan Flavius Panda
由于某种原因,时间戳类型编码可以工作,但是GregorianCalendar不能,两者都没有列在AlexeyRomanov评论中提到的文件中。 - Răzvan Flavius Panda

2
"在未来的版本中,将添加对其他类型序列化的支持。尽管计划中有此功能,但目前不支持自定义编码器。您可以尝试自己实现该特性,但是官方没有提供任何示例。"
"一种选择是使用一个Seq[Int]成员,并确保它最多只有一个值。"

2
你可以将我的回答和上面的评论结合起来,创建一个名为OptionalInt的case类,它包装了一个Seq[Int]。然后你可以在这个case类中实现isDefinedisEmptyget甚至是getOrElse方法。 - David Griffin
1
@DavidGriffin:您能添加一个答案吗?我的 Scala 有点生疏。我会在此期间尝试实现它。 - Răzvan Flavius Panda
@Alexey Romanov:看起来 Seq[Int] 也被视为不支持的类型,因此它无法工作。 - Răzvan Flavius Panda
@RăzvanPanda 奇怪,它被列在 https://github.com/apache/spark/blob/v1.6.1/sql/core/src/main/scala/org/apache/spark/sql/SQLImplicits.scala#L72 中。 - Alexey Romanov
@AlexeyRomanov 我明白了,你介意试一下吗?也许是我做错了什么,但它对我没有起作用。 - Răzvan Flavius Panda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接