2016-07-21 4 views
1

Я пытаюсь создать набор данных с некоторыми геоданными, используя искру и esri. Если Foo имеет только поле Point, оно будет работать, но если я добавлю другие поля за пределами Point, я получаю ArrayIndexOutOfBoundsException.Spark kryo encoder ArrayIndexOutOfBoundsException

import com.esri.core.geometry.Point 
import org.apache.spark.sql.{Encoder, Encoders, SQLContext} 
import org.apache.spark.{SparkConf, SparkContext} 

object Main { 

    case class Foo(position: Point, name: String) 

    object MyEncoders { 
    implicit def PointEncoder: Encoder[Point] = Encoders.kryo[Point] 

    implicit def FooEncoder: Encoder[Foo] = Encoders.kryo[Foo] 
    } 

    def main(args: Array[String]): Unit = { 
    val sc = new SparkContext(new SparkConf().setAppName("app").setMaster("local")) 
    val sqlContext = new SQLContext(sc) 
    import MyEncoders.{FooEncoder, PointEncoder} 
    import sqlContext.implicits._ 
    Seq(new Foo(new Point(0, 0), "bar")).toDS.show 
    } 
} 

Исключение в потоке "основного" java.lang.ArrayIndexOutOfBoundsException: 1 в org.apache.spark.sql.execution.Queryable $$ anonfun $ FormatString $ 1 $$ anonfun $ применять $ 2.Apply (Queryable.scala: 71) в org.apache.spark.sql.execution.Queryable $$ anonfun $ FormatString $ 1 $$ anonfun $ применять $ 2.Apply (Queryable.scala: 70) на scala.collection.TraversableLike $ WithFilter $$ anonfun $ foreach $ 1.apply (TraversableLike.scala: 772) at scala.collection.mutable.ResizableArray $ class.foreach (ResizableArray.scal а: 59) в scala.collection.mutable.ArrayBuffer.foreach (ArrayBuffer.scala: 47) на scala.collection.TraversableLike $ WithFilter.foreach (TraversableLike.scala: 771) в org.apache.spark. sql.execution.Queryable $$ anonfun $ formatString $ 1.apply (Queryable.scala: 70) at org.apache.spark.sql.execution.Queryable $$ anonfun $ formatString $ 1.apply (Queryable.scala: 69) at scala.collection.mutable.ArraySeq.foreach (ArraySeq.scala: 73) в org.apache.spark.sql.execution.Queryable $ class.formatString (Queryable.scala: 69) at org.apache.spark.sql .Dataset.formatString (Dataset.scala: 65) в org.apache.spark.sql.Dataset.showString (Dataset.scala: 263) в org.apache.spark.sql.Dataset.show (Dataset.scala: 230) в org.apache.spark.sql.Dataset.show (Dataset.scala: 193) по адресу org.apache.spark.sql.Dataset .show (Dataset.scala: 201) в Main $ .main (Main.scala: 24) в Main.main (Main.scala)

ответ

0

Kryo создать кодер для сложных типов данных, основанных на Spark SQL Data Types. Таким образом, проверьте результат схемы, Kryo создать:

val enc: Encoder[Foo] = Encoders.kryo[Foo] 
println(enc.schema) // StructType(StructField(value,BinaryType,true)) 
val numCols = schema.fieldNames.length // 1 

Так у вас есть один данные столбцов в наборе данных, и это в двоичном формате. Но странно, почему Spark пытается показать Dataset более чем в одном столбце (и эта ошибка возникает). Чтобы исправить это, обновите версию Spark до версии 2.0.0.

С помощью Spark 2.0.0 у вас все еще есть проблемы с типами данных столбцов. Я надеюсь писать руководство схема работает, если вы можете написать StructType для ESRI Поинт класса:

val schema = StructType(
    Seq(
    StructField("point", StructType(...), true), 
    StructField("name", StringType, true) 
    ) 
) 

val rdd = sc.parallelize(Seq(Row(new Point(0,0), "bar"))) 

sqlContext.createDataFrame(rdd, schema).toDS 
+0

Согласно [это] (http://stackoverflow.com/a/32454596/1805756), я думаю, было бы лучше не идти после пользовательского 'StructType'. Я буду придерживаться 'RDD'. – Mehraban

+0

Это не должно быть 'StructType', это должно быть' BinaryType'. – Mehraban

+0

Это зависит от вашей потребности, если вы хотите вложенную схему или нет, и как класс Point является сложным. –

Смежные вопросы