2016-07-21 113 views
1

我試圖創建使用火花和ESRI一些地理數據的數據集。如果Foo只有Point領域,它會工作,但如果我添加一些其他的領域超過Point,我得到ArrayIndexOutOfBoundsException異常。星火KRYO編碼器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 
    } 
} 

異常線程 「main」 java.lang.ArrayIndexOutOfBoundsException:1 在 org.apache.spark.sql.execution.Queryable $$ anonfun $ formatString的$ 1 $$ anonfun $適用$ 2.適用(Queryable.scala:71) at org.apache.spark.sql.execution.Queryable $$ anonfun $ formatString $ 1 $$ anonfun $ apply $ 2.apply(Queryable.scala:70) at scala.collection.TraversableLike $ WithFilter $$ anonfun $ $的foreach 1.適用(TraversableLike.scala:772) 在 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) 在scala.collection.mutable.ArraySeq.foreach(ArraySeq.scala:73)在 org.apache.spark.sql.execution.Queryable $ class.formatString(Queryable.scala:69) 在org.apache.spark.sql .Dataset.formatString(Dataset.scala:65)at org.apache.spark.sql.Dataset.showString(Dataset.scala:263)at 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.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嘗試在多列中顯示數據集(並且發生該錯誤)。要解決此問題,請將Spark版本升級到2.0.0。

利用星火2.0.0,您仍然對列中的數據類型的問題。我希望寫手動模式工作,如果你能爲ESRI Point類寫StructType:

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類是如何複雜。 –

相關問題