2016-11-10 11 views
2

ケースクラスTを使用して実装する必要があるScala特性を作成したいのですが、データをロードしてSpark Dataset私はScalaがTが大文字小文字クラスでなければならないことを知らないため、エンコーダを格納することができないというエラーを受けました。どのようにコンパイラに伝えることができますか?私はどこかで、Productについて言及すべきところを見てきましたが、そのようなクラスは定義されていません。これを行うための他の方法を自由に提案してください!Scalaでデータセットを作成する一般的なケースクラスを使用して特性を実装する方法

次のコードがありますが、エラーでコンパイルされません。42:エラー:データセットに格納されている型のエンコーダが見つかりません。プリミティブ型(INT、文字列など)と製品の種類(ケースクラス)sqlContext.implicits._ [INFO]の.asをインポートすることでサポートされている[T]

私はスパーク1.6.1

を使用していますコード:

import org.apache.spark.{SparkConf, SparkContext} 
import org.apache.spark.sql.{Dataset, SQLContext}  

/** 
     * A trait that moves data on Hadoop with Spark based on the location and the granularity of the data. 
     */ 
    trait Agent[T] { 
     /** 
     * Load a Dataframe from the location and convert into a Dataset 
     * @return Dataset[T] 
     */ 
     protected def load(): Dataset[T] = { 
     // Read in the data 
     SparkContextKeeper.sqlContext.read 
      .format("com.databricks.spark.csv") 
      .option("header", header) // Use first line of all files as header 
      .option("inferSchema", "true") // Automatically infer data types 
      .option("delimiter", "|") // Deloitte always expects pipe as a delimiter 
      .option("dateFormat","yyyy-MM-dd") // Deloitte always expects this kind of Date format 
      .load("/iacc/eandis/landing/raw/" + location + "/2016/10/01/") 
      .as[T] 
     } 
    } 
+0

可能な複製http://stackoverflow.com/questions/34715611/why-is-the-error-unable-to-find-encoder-for-type-stored-in-a-dataset-when-enco http://stackoverflow.com/questions/38664972/why-is-unable-to-find-encoder-for-type-stored-in-a-dataset-when-creating-a-dat – Shankar

答えて

3

あなたのコードは3つの事欠落しています。確かに

  • を、あなたはコンパイラはTがProductのサブクラスであることを(すべてのScalaのケースクラスとタプルのスーパークラス)を知っている必要があります
  • コンパイラ実際のケースクラスのTypeTagClassTagも必要になります。これは、残念ながらsqlContext.implicits._

の種類消去

  • インポートを克服するためにスパークによって暗黙的に使用されている、あなたはコンテキスト境界トレイトで型パラメータを追加することはできませんので、最も簡単な回避策が使用することです代わりにabstract class

    import scala.reflect.runtime.universe.TypeTag 
    import scala.reflect.ClassTag 
    
    abstract class Agent[T <: Product : ClassTag : TypeTag] { 
        protected def load(): Dataset[T] = { 
        val sqlContext: SQLContext = SparkContextKeeper.sqlContext 
        import sqlContext.implicits._ 
        sqlContext.read.// same... 
        } 
    } 
    

    明らかに、これは形質を使用するのと同じではなく、この設計は仕事に最適ではないことを示唆しているかもしれません。別の方法としては、オブジェクトloadを配置し、メソッドに型パラメータを動いている:

    object Agent { 
        protected def load[T <: Product : ClassTag : TypeTag](): Dataset[T] = { 
        // same... 
        } 
    } 
    
    1が好ましく、主にあなたがloadを呼び出すするつもりどこで、どのように任されて、あなたは何を計画している

    その結果と関係する。

  • +0

    ソリューションをありがとう、便利ですデザインにもコメント!私はすでにあなたの最初と3番目の発言を試しましたが、私はトリックを行うために必要な2番目のもの:) Btw、私は作成しているすべてのデータセットに対してAgentを継承するので抽象クラスも良いと思います – Sparky

    0

    次の2つのアクションを実行する必要があります。

    1. があなたの輸入にimport sparkSession.implicits._を追加
    2. があなたを作りますRトレイトtrait Agent[T <: Product]
    関連する問題