我有一个简单的spark任务的问题,它读取Avro文件,然后将其保存为蜂巢镶嵌板表格。
我有两种类型的文件,大体上是一样的,但是关键的结构有点不同--字段名。
类型1
root
|-- pk: strucnt (nullable = true)
|-- term_id: string (nullale = true)类型2
root
|-- pk: strucnt (nullable = true)
|-- id: string (nullale = true)我正在用spark-avro阅读Avro。然后将此DF映射到bean,如下所示
Dataset<SomeClass> df = avroDF.as(Encoders.bean(SomeClass.class));SomeClass是一个简单的单字段类,带有getter和setter。
public class SomeClass{
private String term_id;
...
}所以如果我读的是Avro类型1-没问题。但是如果我读的是Avro类型2--错误就发生了。如果我将字段名更改为private String id;,反之亦然
我的问题有没有通用的解决方案?我找到了@AvroName,但它不允许设置多个名称。谢谢。
发布于 2018-01-29 21:16:16
可能的解决方案是
StructType avroExtendedSchema = avroDF.schema().add("id",DataTypes.StringType);
avroDF.map(row->RowFactory(row.getStruct(0),row.getStruct(0).getString(0)),
RowEncoder.apply(avroExtendedSchema)).toDF();因此,DF的第二个字段将被命名为"id“,并包含字符串key。第一个"pk“结构可以在将来删除。
avroDF.drop("pk");PS我发现了第三种类型的模式:
root
|-- pk: strucnt (nullable = true)
|-- id: int(nullale = true)因此,最终的代码如下:
DataType keyType = avroDF.select("pk.*").schema().fields[0].dataType();
StructType avroExtendedSchema = avroDF.schema().add("id",keyType);
avroDF.map(row->RowFactory(row.getStruct(0),row.getStruct(0).get(0)),
RowEncoder.apply(avroExtendedSchema)).drop("pk").toDF();此代码适用于任何原始字符串键。
发布于 2018-01-29 16:55:46
只有一种方法是将dataset fieldname更改为架构中的名称。请使用此示例来完成此操作:
val newName = Seq("id", "x1", "x2", "x3")
Dataset<SomeClass> df = avroDF.toDF(newNames: _*).as(Encoders.bean(SomeClass.class));您不能将dataframe转换为具有不同字段名的BeanClass。
https://stackoverflow.com/questions/48496550
复制相似问题