2016-08-03 38 views
10

Ich verwende Apache Spark 2.0 und case class für Erwähnung Schema für DetaSet erstellen. Wenn ich versuche, benutzerdefinierten Encoder zu definieren, nach How to store custom objects in Dataset?, für java.time.LocalDate ich habe folgende Ausnahme:Apache Spark 2.0: java.lang.UnsupportedOperationException: Kein Encoder gefunden für java.time.LocalDate

java.lang.UnsupportedOperationException: No Encoder found for java.time.LocalDate 
- field (class: "java.time.LocalDate", name: "callDate") 
- root class: "FireService" 
at org.apache.spark.sql.catalyst.ScalaReflection$.org$apache$spark$sql$catalyst$ScalaReflection$$serializerFor(ScalaReflection.scala:598) 
at org.apache.spark.sql.catalyst.ScalaReflection$$anonfun$9.apply(ScalaReflection.scala:592) 
at org.apache.spark.sql.catalyst.ScalaReflection$$anonfun$9.apply(ScalaReflection.scala:583) 
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241) 
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241) 
at scala.collection.immutable.List.foreach(List.scala:381) 
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241) 
............ 

Es folgt von Code:

case class FireService(callNumber: String, callDate: java.time.LocalDate) 
implicit val localDateEncoder: org.apache.spark.sql.Encoder[java.time.LocalDate] = org.apache.spark.sql.Encoders.kryo[java.time.LocalDate] 

val fireServiceDf = df.map(row => { 
val dateFormatter = java.time.format.DateTimeFormatter.ofPattern("MM/dd /yyyy") 
FireService(row.getAs[String](0), java.time.LocalDate.parse(row.getAs[String](4), dateFormatter)) 
}) 

Wie wir Dritter api des Geber für die Funken definieren können?

aktualisieren

Wenn ich den Encoder für ganze Fall-Klasse erstellen, df.map.. das Objekt in binären, wie anbei:

implicit val fireServiceEncoder: org.apache.spark.sql.Encoder[FireService] = org.apache.spark.sql.Encoders.kryo[FireService] 

val fireServiceDf = df.map(row => { 
val dateFormatter = java.time.format.DateTimeFormatter.ofPattern("MM/dd/yyyy") 
FireService(row.getAs[String](0), java.time.LocalDate.parse(row.getAs[String](4), dateFormatter)) 
}) 

fireServiceDf: org.apache.spark.sql.Dataset[FireService] = [value: binary] 

I Karte für fireservice erwarten, aber das Rück binäre Karten .

Antwort

4

Wie der letzte Kommentar dort sagt, "wenn Klasse eine Feldleiste enthält, benötigen Sie Encoder für ein ganzes Objekt." Sie müssen einen impliziten Encoder für FireService selbst bereitstellen; Andernfalls erstellt Spark einen für Sie mit SQLImplicits.newProductEncoder[T <: Product : TypeTag]: Encoder[T]. Sie können anhand des Typs sehen, dass keine implicit Encoder-Parameter für Felder verwendet werden, sodass die Anwesenheit von localDateEncoder nicht verwendet werden kann.

Spark könnte geändert werden, um dies z. Verwenden der Shapeless-Bibliothek oder direktes Verwenden von Makros; Ich weiß nicht, ob das der Plan in der Zukunft ist.

+0

Hey @Alexey ich habe deinen Punkt immer noch bekomme ich keinen genauen Grund, warum wir vollständige Objekt Formatierer benötigten? –

+0

Ich habe deinen Standpunkt verstanden. Ich aktualisiere auch die Frage, weil meine Daten jetzt in Binär konvertiert werden. Wenn ich Timestamp anstelle von LocalDate verwende, wird das Datenschema als FireService erstellt, andernfalls als Binary. –

+0

Bitte fragen Sie das als separate Frage. Bearbeiten Sie im Allgemeinen keine Frage, um eine andere Frage zu stellen. –