我有org.apache.avro.generic.GenericRecord
,avro schema
的列表,我们需要在dataframe
API的帮助下创建SQLContext
,以创建它需要的dataframe
{ {1}}和RDD
的{1}}。创建DF的先决条件是我们应该有org.apache.spark.sql.Row的RDD,它可以使用下面的代码来实现,但是它有些不起作用并且给出错误,示例代码。
org.apache.spark.sql.Row
但是在创建avro schema
时会出错。有人可以帮我解决上面代码中的错误。除此之外,如果某人有不同的逻辑来转换和创建 1. Convert GenericRecord to Row
import org.apache.spark.sql.Row
import org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema
import org.apache.avro.Schema
import org.apache.spark.sql.types.StructType
def convertGenericRecordToRow(genericRecords: Seq[GenericRecord], avroSchema: Schema, schemaType: StructType): Seq[Row] =
{
val fields = avroSchema.getFields
var rows = new Seq[Row]
for (avroRecord <- genericRecords) {
var avroFieldsSeq = Seq[Any]();
for (i <- 0 to fields.size - 1) {
avroFieldsSeq = avroFieldsSeq :+avroRecord.get(fields.get(i).name)
}
val avroFieldArr = avroFieldsSeq.toArray
val genericRow = new GenericRowWithSchema(avroFieldArr, schemaType)
rows = rows :+ genericRow
}
return rows;
}
2. Convert `Avro schema` to `Structtype`
Use `com.databricks.spark.avro.SchemaConverters -> toSqlType` function , it will convert avro schema to StructType
3. Create `Dataframe` using `SQLContext`
val rowSeq= convertGenericRecordToRow(genericRecords, avroSchema, schemaType)
val rowRdd = sc.parallelize(rowSeq, 1)
val finalDF =sqlContext.createDataFrame(rowRDD,structType)
。
每当我在Dataframe上调用任何操作时,它都会执行DAG并尝试创建DF对象,但是在这种情况下,它会因以下异常而失败
DataFrame
在此之后我试图在spark提交的jar参数中给出正确的版本jar,并使用其他参数作为--conf spark.driver.userClassPathFirst = true 但现在它失败了MapR
dataframe
我们正在使用MapR分布和spark-submit中的类路径更改后,它失败并出现上述异常。
有人可以帮助我或者我基本需要它将Avro GenericRecord转换为Spark Row,这样我就可以用它创建Dataframe,请帮助
感谢。
答案 0 :(得分:3)
也许这可以帮助以后再玩的人。
由于spark-avro
已被弃用,现在已集成到Spark中,因此可以通过另一种方式来实现。
import org.apache.spark.sql.avro._
import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.catalyst.encoders.RowEncoder
...
val avroSchema = data.head.getSchema
val sparkTypes = SchemaConverters.toSqlType(avroSchema).dataType.asInstanceOf[StructType]
val converter = new AvroDeserializer(avroSchema, sparkTypes)
val enconder = RowEncoder.apply(sparkTypes).resolveAndBind()
val rows = data.map { record =>
enconder.fromRow(converter.deserialize(record).asInstanceOf[InternalRow])
}
val df = sparkSession.sqlContext.createDataFrame(sparkSession.sparkContext.parallelize(rows), sparkTypes)
答案 1 :(得分:0)
希望这会有所帮助。在第一部分中,您可以找到如何从GenericRecord转换为Row
答案 2 :(得分:0)
从RDD [GenericRecord]创建数据框时,步骤很少
使用com.databricks.spark.avro.SchemaConverters.createConverterToSQL( sourceAvroSchema:Schema,targetSqlType:DataType)
这是spark-avro 3.2版本中的私有方法。如果我们有相同或小于3.2,那么将此方法复制到您自己的util类中并使用它,否则直接使用它。
val rdd = ssc.sparkContext.parallelize(rowSeq,numParition)val dataframe = sparkSession.createDataFrame(rowRDD,schemaType)
这解决了我的问题。