wake-up-neo.com

Warum wird beim Erstellen eines Datensatzes der benutzerdefinierten Fallklasse "Encoder für in einem Datensatz gespeicherten Typ nicht gefunden"?

Spark 2.0 (final) mit Scala 2.11.8. Der folgende supereinfache Code liefert den Kompilierungsfehler Error:(17, 45) Unable to find encoder for type stored in a Dataset. Primitive types (Int, String, etc) and Product types (case classes) are supported by importing spark.implicits._ Support for serializing other types will be added in future releases.

import org.Apache.spark.sql.SparkSession

case class SimpleTuple(id: Int, desc: String)

object DatasetTest {
  val dataList = List(
    SimpleTuple(5, "abc"),
    SimpleTuple(6, "bcd")
  )

  def main(args: Array[String]): Unit = {
    val sparkSession = SparkSession.builder.
      master("local")
      .appName("example")
      .getOrCreate()

    val dataset = sparkSession.createDataset(dataList)
  }
}
52
clay

Spark Datasets erfordert Encoders für den Datentyp, der gespeichert werden soll. Für gängige Typen (Atomics, Produkttypen) stehen eine Reihe vordefinierter Encoder zur Verfügung, die Sie jedoch erst aus SparkSession.implicits damit es funktioniert:

val sparkSession: SparkSession = ???
import sparkSession.implicits._
val dataset = sparkSession.createDataset(dataList)

Alternativ können Sie direkt eine explizite angeben

import org.Apache.spark.sql.{Encoder, Encoders}

val dataset = sparkSession.createDataset(dataList)(Encoders.product[SimpleTuple])

oder implizit

implicit val enc: Encoder[SimpleTuple] = Encoders.product[SimpleTuple]
val dataset = sparkSession.createDataset(dataList)

Encoder für den gespeicherten Typ.

Beachten Sie, dass Enocders auch eine Reihe vordefinierter Encoders für atomare Typen und Encoders für komplexe Typen bereitstellen kann, die mit ExpressionEncoder abgeleitet werden =.

Weitere Lektüre:

75
zero323

Beachten Sie für andere Benutzer (Ihre ist korrekt), dass es auch wichtig ist, dass die case class wird außerhalb des Bereichs object definiert. So:

Schlägt fehl:

object DatasetTest {
  case class SimpleTuple(id: Int, desc: String)

  val dataList = List(
    SimpleTuple(5, "abc"),
    SimpleTuple(6, "bcd")
  )

  def main(args: Array[String]): Unit = {
    val sparkSession = SparkSession.builder
      .master("local")
      .appName("example")
      .getOrCreate()
    val dataset = sparkSession.createDataset(dataList)
  }
}

Fügen Sie die Implicits hinzu. Schlägt immer noch mit demselben Fehler fehl:

object DatasetTest {
  case class SimpleTuple(id: Int, desc: String)

  val dataList = List(
    SimpleTuple(5, "abc"),
    SimpleTuple(6, "bcd")
  )

  def main(args: Array[String]): Unit = {
    val sparkSession = SparkSession.builder
      .master("local")
      .appName("example")
      .getOrCreate()

    import sparkSession.implicits._
    val dataset = sparkSession.createDataset(dataList)
  }
}

Werke:

case class SimpleTuple(id: Int, desc: String)

object DatasetTest {   
  val dataList = List(
    SimpleTuple(5, "abc"),
    SimpleTuple(6, "bcd")
  )

  def main(args: Array[String]): Unit = {
    val sparkSession = SparkSession.builder
      .master("local")
      .appName("example")
      .getOrCreate()

    import sparkSession.implicits._
    val dataset = sparkSession.createDataset(dataList)
  }
}

Hier ist der relevante Fehler: https://issues.Apache.org/jira/browse/SPARK-1354 , hoffentlich wird er in der nächsten Version von Spark) behoben = 2.

(Edit: Sieht so aus, als wäre dieser Bugfix tatsächlich in Spark 2.0.0 ... Ich bin mir also nicht sicher, warum dies immer noch fehlschlägt).

44
MrProper