我为简单的类层次结构自动生成了Avro架构:
trait T {def name: String}
case class A(name: String, value: Int) extends T
case class B(name: String, history: Array[String]) extends T
看起来像这样:
[{
"name": "org.example.schema.raw.A",
"type": "record",
"fields": [{
"name": "name",
"type": "string"
}, {
"name": "value",
"type": "int"
}]
}, {
"name": "org.example.schema.raw.B",
"type": "record",
"fields": [{
"name": "name",
"type": "string"
}, {
"name": "history",
"type": {
"type": "array",
"items": "string"
}
}]
}]
此模式适用于使用普通Avro API将数据从JSON读取到GenericRecord
。我尝试实现的下一步是使用GenericRecord
将所有此类AvroParquetWriter
对象存储到单个镶木地板文件中:
val writer = new AvroParquetWriter[GenericRecord](file, schema)
writer.write(record)
writer.close()
此代码在第一行
失败java.lang.IllegalArgumentException: Avro schema must be a record.
at parquet.avro.AvroSchemaConverter.convert(AvroSchemaConverter.java:96)
at parquet.avro.AvroParquetWriter.writeSupport(AvroParquetWriter.java:137)
at parquet.avro.AvroParquetWriter.<init>(AvroParquetWriter.java:54)
at parquet.avro.AvroParquetWriter.<init>(AvroParquetWriter.java:86)
难怪,AvroSchemaConverter包含以下几行:
if (!avroSchema.getType().equals(Schema.Type.RECORD)) {
throw new IllegalArgumentException("Avro schema must be a record.");
}
我的架构类型是UNION。将UNION模式映射(合并)到RECORD模式或任何其他建议中的任何想法/帮助都非常感谢。
解
1)使用union scheme将输入中的JSON读入GenericRecord
2)获取或创建AvroParquetWriter
类型:
val writer = writers.getOrElseUpdate(record.getType, new AvroParquetWriter[GenericRecord](getPath(record.getType), record.getShema)
3)将记录写入文件:
writer.write(record)
4)当从输入中消耗所有数据时关闭所有写入器:
writers.values.foreach(_.close())
5)将目录中的数据加载到Spark SQL DataFrame:
sqlContext.option("mergeSchema", "true").parquet("/tmp/data/")
6)数据可以按原样处理或存储 - 它已经由Spark合并:
df.write.format("parquet").save("merged.parquet")
答案 0 :(得分:0)
要回答有关合并的问题:您可以使用以下case class Merged(name: String, value: Option[Int], history: Option[Array[String]])
并使用生成的模式来编写数据。
通常,如果您的架构向前兼容A和B,它将正确写入。
或者,正如你所说,avro不会让你把所有数据都写在同一个文件中,也许你可以按类型分割输出,每种类型写一个文件?我知道在我能想到的大多数用例中我可能会这样做,但也许它并不适合你。
答案 1 :(得分:0)
您可以使用Case类(即Record)来包装特征。
案例类Reord [K](键:K,值:T)