我正在尝试在下面的代码中处理多个avro文件。我们的想法是先在列表中获取一系列avro文件。然后打开每个avro文件并生成元组的循环(string,int)。然后最后用密钥对元组流进行分组并对整数求和。
object AvroCopyUtil {
def main(args: Array[String]) : Unit = {
val conf = new SparkConf().setAppName("Leads Data Analysis").setMaster("local[*]")
val sc = new SparkContext(conf)
val fs = FileSystem.get(new Configuration())
val avroList = GetAvroList(fs, args(0))
avroList.flatMap(av =>
sc.newAPIHadoopFile[AvroKey[GenericRecord], NullWritable, AvroKeyInputFormat[GenericRecord]](av)
.map(r => (r._1.datum.get("field").toString, 1)))
.reduceByKey(_ + _)
.foreach(println)
}
def GetAvroList(fs: FileSystem, input: String) : List[String] = {
// get all children
val masterList : List[FileStatus] = fs.listStatus(new Path(input)).toList
val (allFiles, allDirs) = masterList.partition(x => x.isDirectory == false)
allFiles.map(_.getPath.toString) ::: allDirs.map(_.getPath.toString).flatMap(x => GetAvroList(fs, x))
}
}
我得到的编译错误是
[error] found : org.apache.spark.rdd.RDD[(org.apache.avro.mapred.AvroKey[org.apache.avro.generic.GenericRecord], org.apache.hadoop.io.NullWritable)]
[error] required: TraversableOnce[?]
[error] avroRdd.flatMap(av => sc.newAPIHadoopFile[AvroKey[GenericRecord], NullWritable, AvroKeyInputFormat[GenericRecord]](av))
[error] ^
[error] one error found
编辑:根据下面的建议,我试过
val rdd = sc.newAPIHadoopFile[AvroKey[GenericRecord], NullWritable,
AvroKeyInputFormat[GenericRecord]](avroList.mkString(","))
但是我收到了错误
Exception in thread "main" java.lang.IllegalArgumentException: java.net.URISyntaxException: Illegal character in scheme name at index 0: 2015-10-
15-00-1576041136-flumetracker.foo.com-FooAvroEvent.1444867200044.avro,hdfs:
答案 0 :(得分:1)
您的功能是不必要的。您还试图在转换中创建一个RDD,这个转换并不真正有意义。转换(在这种情况下,flatMap
)在RDD之上运行,RDD中的记录将是转换的内容。在flatMap
的情况下,匿名函数的预期输出是TraversableOnce
对象,然后通过转换将其展平为多个记录。看看你的代码,你真的不需要做flatMap
因为简单map
就足够了。请记住,由于RDD的不变性,您必须始终将转换重新分配给新值。
尝试类似:
val avroRDD = sc.newAPIHadoopFile[AvroKey[GenericRecord], NullWritable, AvroKeyInputFormat[GenericRecord]](filePath)
val countsRDD = avroRDD.map(av => (av._1.datum.get("field1").toString, 1)).reduceByKey(_ + _)
似乎您可能需要花一些时间来掌握Spark的一些基本框架细微差别。我建议您完全阅读Spark Programming Guide。最后,如果您想使用Avro,请查看spark-avro尽可能多地使用Avro处理锅炉板(并且DataFrames可能更直观,更易于用于您的用例)
(编辑:)
您似乎可能误解了如何加载要在Spark中处理的数据。 parallelize()
方法用于跨RDD分发集合,而不是文件中的数据。要执行后者,您实际上只需要为newAPIHadoopFile()
加载器提供以逗号分隔的输入文件列表。因此,假设您的GetAvroList()
函数有效,您可以执行以下操作:
val avroList = GetAvroList(fs, args(0))
val avroRDD = sc.newAPIHadoopFile[AvroKey[GenericRecord], NullWritable, AvroKeyInputFormat[GenericRecord]](avroList.mkString(","))
val countsRDD = avroRDD.map(av => (av._1.datum.get("field1").toString, 1)).reduceByKey(_ + _)
flatMappedRDD.foreach(println)