Spark SQL - 包含列表或数组作为元素的元组的编码器

时间:2018-05-02 01:47:56

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

使用Spark 2.2 + Java 1.8

我有两种自定义数据类型" Foo"和" Bar"。每一个都实现了可序列化。' Foo'与' Bar'有一对多的关系。所以他们的关系表现为元组:

Tuple2<Foo, List<Bar>>

通常,当我有1:1的关系时,我可以编码为我的自定义类型:

Encoder<Tuple2<Foo,Bar>> fooBarEncoder = Encoders.tuple(Encoders.bean(Foo.class),Encoders.bean(Bar.class));

然后用来编码我的数据集

Dataset<Tuple2<Foo,Bar>> fooBarSet = getSomeData().as(fooBarEncoder);

但是当我将列表(或数组)作为Tuple2元素时,我无法找到编码方案的方法。我希望能够为第二个元素提供一个编码器,如下所示:

Encoder<Tuple2<Foo,List<Bar>>> fooBarEncoder = Encoders.tuple(Encoders.bean(Foo.class), List<Bar>.class);

然后编码到我的数据集:

Dataset<Tuple2<Foo,List<Bar>>> fooBarSet = getSomeData().as(fooBarEncoder)

但显然我不能在像List

这样的参数化类型上调用.class

我知道对于String和基本类型,数组由spark implicits支持,例如:

sparkSession.implicits().newStringArrayEncoder()

但是,如何为自定义类类型的List或Array创建编码器?

2 个答案:

答案 0 :(得分:0)

我不确定在你的设置中如何实现这种方法,但是这里有。为列表创建一个包装类并尝试一下。

public class BarList implements Serializable {
    List<Bar> list;

    public List<Bar> getList() {
        return list;
    }
    public void setList(List<Bar> l) {
        list = l;
    }
}

答案 1 :(得分:0)

我不知道是否可能。我尝试了下面的Scala,尝试帮助,通过首先教导如何编码X,然后List [X]以及最后一个包含List [X]的元组(未在下面显示)来确定我可以构建编码器:

import org.apache.spark.sql.Encoders
import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder
import scala.beans.BeanProperty

class X(@BeanProperty var field: String) extends Serializable
case class Z(field: String)

implicit val XEncoder1 = Encoders.bean(classOf[X])

implicit val ZEncoder = Encoders.product[Z]

val listXEncoder = ExpressionEncoder[List[X]] // doesn't work
val listZEncoder = ExpressionEncoder[List[Z]]

listZEncoder工作正常

切换到使用

implicit val XEncoder2 = org.apache.spark.sql.Encoders.kryo[X]

仍然不适用于listXEncoder

错误最终发生在催化剂ScalaReflection的一个地方,这超出了我的范围。