【问题标题】:Spark SQL: Nested classes to parquet errorSpark SQL:嵌套类到镶木地板错误
【发布时间】:2016-03-06 04:44:33
【问题描述】:

我似乎无法为镶木地板写信 JavaRDD<T> 其中 T 表示 Person 类。我把它定义为

public class Person implements Serializable
{
    private static final long serialVersionUID = 1L;
    private String name;
    private String age;
    private Address address;
....

Address:

public class Address implements Serializable
{
    private static final long serialVersionUID = 1L;
    private String City; private String Block;
    ...<getters and setters>

然后我像这样创建一个JavaRDD

JavaRDD<Person> people = sc.textFile("/user/johndoe/spark/data/people.txt").map(new Function<String, Person>()
    {
        public Person call(String line)
        {
            String[] parts = line.split(",");
            Person person = new Person();
            person.setName(parts[0]);
            person.setAge("2");
            Address address = new Address("HomeAdd","141H");
            person.setAddress(address);
            return person;
        }
    });

注意 - 我手动将 Address 设置为对所有人都相同。这基本上是一个嵌套的 RDD。在尝试将其保存为镶木地板文件时:

DataFrame dfschemaPeople = sqlContext.createDataFrame(people, Person.class);
dfschemaPeople.write().parquet("/user/johndoe/spark/data/out/people.parquet");    

地址类是:

import java.io.Serializable;
public class Address implements Serializable
{
    public Address(String city, String block)
    {
        super();
        City = city;
        Block = block;
    }
    private static final long serialVersionUID = 1L;
    private String City;
    private String Block;
    //Omitting getters and setters
}

我遇到了错误:

原因:java.lang.ClassCastException:com.test.schema.Address 无法转换为 org.apache.spark.sql.Row

我正在运行 spark-1.4.1。

  • 这是一个已知的错误吗?
  • 如果我通过导入相同格式的嵌套 JSON 文件来做同样的事情,我可以保存到镶木地板。
  • 即使我创建了一个子 DataFrame,例如:DataFrame dfSubset = sqlContext.sql("SELECT address.city FROM PersonTable");,我仍然会遇到同样的错误

那是什么?如何从文本文件中读取复杂的数据结构并保存为镶木地板?看来我做不到。

【问题讨论】:

  • 我这样做了,没有任何问题。它输出到标准输出:System.out.println(dfschemaPeople.count()); 当保存到镶木地板时,我得到了这个错误。请注意,如果我有 JSON 数据可以写入镶木地板,那么只有类对象我不能。

标签: java apache-spark apache-spark-sql parquet


【解决方案1】:

您正在使用有限制的 java api

来自火花文档: http://spark.apache.org/docs/1.4.1/sql-programming-guide.html#interoperating-with-rdds

Spark SQL 支持自动将 JavaBean 的 RDD 转换为 DataFrame。使用反射获得的 BeanInfo 定义了表的模式。目前,Spark SQL 不支持包含嵌套或复杂类型(如列表或数组)的 JavaBean。您可以通过创建一个实现 Serializable 并为其所有字段具有 getter 和 setter 的类来创建 JavaBean。 使用 scala 案例类,它将起作用(更新为写入镶木地板格式)

import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD

case class Address(city:String, block:String);
case class Person(name:String,age:String, address:Address);
object Test2 {
  def main(args: Array[String]): Unit = {

     val conf = new SparkConf().setAppName("Simple Application").setMaster("local");
      val sc = new SparkContext(conf)
      val sqlContext = new org.apache.spark.sql.SQLContext(sc);
      import sqlContext.implicits._
      val people = sc.parallelize(List(Person("a", "b", Address("a", "b")), Person("c", "d", Address("c", "d"))));

      val df  = sqlContext.createDataFrame(people);
      df.write.mode("overwrite").parquet("/tmp/people.parquet")
  }
}

【讨论】:

  • 谢谢!我不知何故错过了该页面上的那一行。所以这是一个限制。我确实找到了一个黑客。如果将复杂对象转换为 JSON 并将 JSON 转换为 DataFrame,那么我可以保存为 parquet。 Java Bean 不起作用,但 JSON 可以!
  • 它很容易被忽略,因为它出现在 java 选项卡中...我有同样的问题
猜你喜欢
  • 2016-07-04
  • 1970-01-01
  • 2020-03-12
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 2019-11-20
相关资源
最近更新 更多