복붙노트

[SCALA] 왜 사용자 정의 케이스 클래스의 데이터 집합을 만들 때 "데이터 집합에 저장 유형에 대한 인코더를 찾을 수 없습니다"인가?

SCALA

왜 사용자 정의 케이스 클래스의 데이터 집합을 만들 때 "데이터 집합에 저장 유형에 대한 인코더를 찾을 수 없습니다"인가?

스칼라 2.11.8 2.0 (최종) 스파크. (17, 45) 데이터 집합에 저장 유형에 대한 인코더를 찾을 수 없습니다 : 다음 슈퍼 간단한 코드는 컴파일 오류 오류를 얻을 수 있습니다. 원시 유형 (INT, 문자열 등) 및 제품 유형 (케이스 클래스는) 향후 버전에 추가 될 예정 다른 유형의 직렬화 spark.implicits._ 지원을 가져와 지원됩니다.

import org.apache.spark.sql.SparkSession

case class SimpleTuple(id: Int, desc: String)

object DatasetTest {
  val dataList = List(
    SimpleTuple(5, "abc"),
    SimpleTuple(6, "bcd")
  )

  def main(args: Array[String]): Unit = {
    val sparkSession = SparkSession.builder.
      master("local")
      .appName("example")
      .getOrCreate()

    val dataset = sparkSession.createDataset(dataList)
  }
}

해결법

  1. ==============================

    1.스파크 데이터 집합을 저장하는 것입니다 데이터 유형에 대한 인코더가 필요합니다. 일반적인 유형 (아토, 제품 유형)의 경우이 가능한 미리 정의 된 인코더의 수는 있지만 작동하도록 SparkSession.implicits에서 먼저 다음을 가져올 수 있습니다 :

    스파크 데이터 집합을 저장하는 것입니다 데이터 유형에 대한 인코더가 필요합니다. 일반적인 유형 (아토, 제품 유형)의 경우이 가능한 미리 정의 된 인코더의 수는 있지만 작동하도록 SparkSession.implicits에서 먼저 다음을 가져올 수 있습니다 :

    val sparkSession: SparkSession = ???
    import sparkSession.implicits._
    val dataset = sparkSession.createDataset(dataList)
    

    또는 직접 명시 적으로 제공 할 수 있습니다

    import org.apache.spark.sql.{Encoder, Encoders}
    
    val dataset = sparkSession.createDataset(dataList)(Encoders.product[SimpleTuple])
    

    또는 암시 적

    implicit val enc: Encoder[SimpleTuple] = Encoders.product[SimpleTuple]
    val dataset = sparkSession.createDataset(dataList)
    

    저장된 유형에 대한 인코더.

    Enocders 또한 원자 타입 인코더 소정의 번호를 제공하고, 단지 사람을위한 부호화기, ExpressionEncoder 도출 할 수 있습니다.

    추가 읽기 :

  2. ==============================

    2.다른 사용자 (당신이 올바른지)의 경우,이 경우 클래스가 객체 범위의 외부에서 정의하는 것도 중요합니다 당신이 있습니다. 그래서:

    다른 사용자 (당신이 올바른지)의 경우,이 경우 클래스가 객체 범위의 외부에서 정의하는 것도 중요합니다 당신이 있습니다. 그래서:

    실패 :

    object DatasetTest {
      case class SimpleTuple(id: Int, desc: String)
    
      val dataList = List(
        SimpleTuple(5, "abc"),
        SimpleTuple(6, "bcd")
      )
    
      def main(args: Array[String]): Unit = {
        val sparkSession = SparkSession.builder
          .master("local")
          .appName("example")
          .getOrCreate()
        val dataset = sparkSession.createDataset(dataList)
      }
    }
    

    여전히 같은 오류와 함께 실패의 implicits 추가 :

    object DatasetTest {
      case class SimpleTuple(id: Int, desc: String)
    
      val dataList = List(
        SimpleTuple(5, "abc"),
        SimpleTuple(6, "bcd")
      )
    
      def main(args: Array[String]): Unit = {
        val sparkSession = SparkSession.builder
          .master("local")
          .appName("example")
          .getOrCreate()
    
        import sparkSession.implicits._
        val dataset = sparkSession.createDataset(dataList)
      }
    }
    

    공장:

    case class SimpleTuple(id: Int, desc: String)
    
    object DatasetTest {   
      val dataList = List(
        SimpleTuple(5, "abc"),
        SimpleTuple(6, "bcd")
      )
    
      def main(args: Array[String]): Unit = {
        val sparkSession = SparkSession.builder
          .master("local")
          .appName("example")
          .getOrCreate()
    
        import sparkSession.implicits._
        val dataset = sparkSession.createDataset(dataList)
      }
    }
    

    여기에 관련 버그 : https://issues.apache.org/jira/browse/SPARK-13540, 그래서 잘하면는 점화 2의 다음 릴리스에서 해결 될 것입니다.

    (편집 : 그 버그 수정이 스파크 2.0.0에서 실제로 것 같은데 ... 그래서 난이 계속 실패 이유를 모르겠어요).

  3. ==============================

    3.나는 목표는 간단한 문자 SparkData 프레임을 정의보다는 스칼라 튜플과 암시 적 변환을 사용하는 경우, 간단한 경로는 다음과 같이 직접 스파크 API를 사용하는 것입니다, 내 자신의 질문에 대한 답을 명확히 것입니다 :

    나는 목표는 간단한 문자 SparkData 프레임을 정의보다는 스칼라 튜플과 암시 적 변환을 사용하는 경우, 간단한 경로는 다음과 같이 직접 스파크 API를 사용하는 것입니다, 내 자신의 질문에 대한 답을 명확히 것입니다 :

      import org.apache.spark.sql._
      import org.apache.spark.sql.types._
      import scala.collection.JavaConverters._
    
      val simpleSchema = StructType(
        StructField("a", StringType) ::
        StructField("b", IntegerType) ::
        StructField("c", IntegerType) ::
        StructField("d", IntegerType) ::
        StructField("e", IntegerType) :: Nil)
    
      val data = List(
        Row("001", 1, 0, 3, 4),
        Row("001", 3, 4, 1, 7),
        Row("001", null, 0, 6, 4),
        Row("003", 1, 4, 5, 7),
        Row("003", 5, 4, null, 2),
        Row("003", 4, null, 9, 2),
        Row("003", 2, 3, 0, 1)
      )
    
      val df = spark.createDataFrame(data.asJava, simpleSchema)
    
  4. from https://stackoverflow.com/questions/38664972/why-is-unable-to-find-encoder-for-type-stored-in-a-dataset-when-creating-a-dat by cc-by-sa and MIT license