Scala-Spark程序 - 需要使用基于初始记录的密钥名称保存到S3存储桶中

时间:2015-10-13 03:48:02

标签: scala amazon-s3 apache-spark

我在S3中有一个非常大的记录列表,其布局如下 - textfield1,textfield2,numField1,textfield3,textfield4

我需要通过textField1和textField2对记录进行分组,按照numField1对分组记录进行排序,并将每个组写出到s3存储桶作为关键textfield1-textfield2-numfield1下的记录,其中numfield1是第一条记录的字段值在已排序的组中。

因此,如果我们有输入记录,如下所示

a,b,45,ab45f3,ab45f4 
d,f,29,df29f3,df29f4
c,b,23,cb23f3,cb23f4
a,b,22,ab22f3,ab22f4
c,b,32,cb32f3,cb32f4
d,f,14,df14f3,df14f4

我在输出中需要以下内容:

s3://output-recs/output/a-b-22 with contents
    a, b, 22, ab22f3, ab22f4
    a, b, 45, ab45f3, ab45f4
s3://output-recs/c-b-23 with contents
    c, b, 23, cb23f3, cb23f4
    c, b, 32, cb32f3, cb32f4
s3://output-recs/d-f-14 with contents
    d, f, 14, df14f3, df14f4
    d, f, 29, df29f3, df29f4

这就是我试过的 - 这部分工作但让我有一些松散的结局

val lists = sc.textFile("s3n://input-rec/allrecs") 
               map { line => line.split(",").toList }

val sg = lists.map(rec => ((rec(0), rec(1)), rec)).groupByKey.mapValues 
              { t => t.toList.sortBy(l => l(2)) }

val p = sg.count.toInt

val res = sg.partitionBy(new HashPartitioner(p)).map {
  case (key, value) => value
}.map(l => l.map(_.mkString(",")).mkString("\n"))

res.saveAsTextFile(s"s3n://output-recs/output")

当我尝试这个时,我遇到了几个问题 -

  1. 它分成三组并创建三个PART文件 - 但有时三个PART中的一个是空白而另外两个PART中的一个包含两个。有没有办法强制它,以便每个分区仅限于1集?
  2. 我无法想出一个重命名" PART"的好方法。文件以匹配我想要的命名约定。我能够通过一个后处理脚本执行此操作,该脚本读取第一行,解析并读取前三个字段,并重命名该文件。但是,它似乎不够优雅,并且需要很长时间才能运行大文件。

0 个答案:

没有答案