Apache Spark 2.1:java.lang.UnsupportedOperationException:找不到scala.collection.immutable.Set [String]的编码器

时间:2017-07-10 19:34:02

标签: scala apache-spark apache-spark-encoders

我使用Spark 2.1.1和Scala 2.11.6。我收到以下错误。我没有使用任何案例类。

java.lang.UnsupportedOperationException: No Encoder found for scala.collection.immutable.Set[String]
 field (class: "scala.collection.immutable.Set", name: "_2")
 field (class: "scala.Tuple2", name: "_2")
 root class: "scala.Tuple2"

以下代码部分是stacktrace指向的位置。

val tweetArrayRDD = nameDF.select("namedEnts", "text", "storylines")
    .flatMap {
    case Row(namedEnts: Traversable[(String, String)], text: String, storylines: Traversable[String]) =>
      Option(namedEnts) match {
        case Some(x: Traversable[(String, String)]) =>
          //println("In flatMap:" + x + " ~~&~~ " + text + " ~~&~~ " + storylines)
          namedEnts.map((_, (text, storylines.toSet)))
        case _ => //println("In flatMap: blahhhh")
          Traversable()
      }
    case _ => //println("In flatMap: fooooo")
      Traversable()
  }
  .rdd.aggregateByKey((Set[String](), Set[String]()))((a, b) => (a._1 + b._1, a._2 ++ b._2), (a, b) => (a._1 ++ b._1, a._2 ++ b._2))
  .map { (s: ((String, String), (Set[String], Set[String]))) => {
    //println("In map: " + s)
    (s._1, (s._2._1.toSeq, s._2._2.toSeq))
  }}

1 个答案:

答案 0 :(得分:6)

这里的问题是Spark没有提供开箱即用的Set编码器(它确实为"基元",Seqs,Arrays和其他产品提供编码器支持的类型)。

您可以尝试使用this excellent answerSet[String]创建自己的编码器(更准确地说,是您正在使用的类型的编码器,Traversable[((String, String), (String, Set[String]))],其中包含{ {1}}),您可以使用Set[String]代替Seq解决此问题:

Set

(我使用// ... case Some(x: Traversable[(String, String)]) => //println("In flatMap:" + x + " ~~&~~ " + text + " ~~&~~ " + storylines) namedEnts.map((_, (text, storylines.toSeq.distinct))) // ... 来模仿distinct行为;也可以尝试Set

更新:根据您的评论重新启动Spark 1.6.2 - 区别在于1.6.2,.toSet.toSeq返回Dataset.flatMap而不是RDD因此,不需要对您提供的函数返回的结果进行编码;因此,这确实提出了另一个好的解决方法 - 您可以通过在<{em> Dataset操作之前明确切换到使用RDD 来轻松模拟此行为:

flatMap