неявный кодировщик искры не найден в области видимости

У меня проблема с искрой, уже описанная в искре нестандартный кодировщик kryo not предоставляет схему для UDF, но сейчас создал минимальный образец: https://gist.github.com/geoHeil/dc9cfb8eca5c06fca01fc9fc03431b2f

class SomeOtherClass(foo: Int)
case class FooWithSomeOtherClass(a: Int, b: String, bar: SomeOtherClass)
case class FooWithoutOtherClass(a: Int, b: String, bar: Int)
case class Foo(a: Int)
implicit val someOtherClassEncoder: Encoder[SomeOtherClass] = Encoders.kryo[SomeOtherClass]
val df2 = Seq(FooWithSomeOtherClass(1, "one", new SomeOtherClass(4))).toDS
val df3 = Seq(FooWithoutOtherClass(1, "one", 1), FooWithoutOtherClass(2, "two", 2)).toDS
val df4 = df3.map(d => FooWithSomeOtherClass(d.a, d.b, new SomeOtherClass(d.bar)))

здесь даже оператор createDataSet не работает из-за

java.lang.UnsupportedOperationException: No Encoder found for SomeOtherClass
- field (class: "SomeOtherClass", name: "bar")
- root class: "FooWithSomeOtherClass"

Почему кодировщик не входит в область видимости или, по крайней мере, не в нужной области?

Кроме того, пытаясь указать явный кодировщик, например:

df3.map(d => {FooWithSomeOtherClass(d.a, d.b, new SomeOtherClass(d.bar))}, (Int, String, Encoders.kryo[SomeOtherClass]))

не работает.


person Georg Heiler    schedule 10.07.2017    source источник
comment
Если вам нужен не только двоичный большой двоичный объект, прочтите этот ответ.   -  person Alec    schedule 10.07.2017


Ответы (1)


Это происходит потому, что вы должны использовать кодировщик Kryo для всего стека сериализации, а это означает, что ваш объект верхнего уровня должен иметь кодировщик Kryo. Следующее успешно выполняется в локальной оболочке Spark (интересующее вас изменение находится в первой строке):

  implicit val topLevelObjectEncoder: Encoder[FooWithSomeOtherClass] = Encoders.kryo[FooWithSomeOtherClass]

  val df1 = Seq(Foo(1), Foo(2)).toDF

  val df2 = Seq(FooWithSomeOtherClass(1, "one", new SomeOtherClass(4))).toDS

  val df3 = Seq(FooWithoutOtherClass(1, "one", 1), FooWithoutOtherClass(2, "two", 2)).toDS
  df3.printSchema
  df3.show

  val df4 = df3.map(d => FooWithSomeOtherClass(d.a, d.b, new SomeOtherClass(d.bar)))
  df4.printSchema
  df4.show
  df4.collect
person stefanobaghino    schedule 10.07.2017
comment
Я понимаю. Но это преобразует всю схему в один двоичный столбец. Я бы предпочел иметь несколько (исходный столбец), где один сериализуется через kayo / binary. Возможно ли это? Я видел, как некоторые java-проекты явно сериализуются, например Encoders.tuple(Encoders.STRING(), Encoders.kryo(Mything.class))), что, кажется, обеспечивает желаемое поведение. Однако я пока не знаю, как воспроизвести это в Scala api. - person Georg Heiler; 10.07.2017
comment
Я предполагаю, что вы не можете сделать это case class ни напрямую, ни путем копирования информации, верно? - person stefanobaghino; 10.07.2017
comment
Было бы возможно хотя бы части желаемой функциональности. Однако, глядя на это с точки зрения удобства использования, было бы здорово, если бы я мог применить крио к одному единственному файлу, который сам по себе не является продуктом. - person Georg Heiler; 10.07.2017