烫伤:如何在groupBy('field){.size}之后保留其他字段?

时间:2013-07-06 22:02:11

标签: twitter cascading scalding

所以我的输入数据有两个字段/列:id1& id2,我的代码如下:

TextLine(args("input"))
.read
.mapTo('line->('id1,'id2)) {line: String =>
    val fields = line.split("\t")
        (fields(0),fields(1))
}
.groupBy('id2){.size}
.write(Tsv(args("output")))

输出结果(我假设)两个字段:id2 * size。我有点发现是否可以保留id2值并将其与id2分组并将其添加为另一个字段?

1 个答案:

答案 0 :(得分:8)

我害怕你不能以一种好的方式做到这一点。想想它是如何工作的 - 它将要计数的数据拆分成块并将其发送到不同的进程,每个进程计算它的块,然后单个reducer将它们全部添加到最后。虽然每个进程都在计算,但它不知道整个大小,因此无法添加字段。唯一的方法是在已知整个大小(即连接)后返回并将其添加到数据中。

如果每个组适合内存(并且您可以配置内存),您可以:

Tsv(args("input"), ('id1, 'id2))
.groupBy('id2)(_.size.toList[(String, String)](('id1, 'id2) -> 'list))
.flatMapTo[(Iterable[(String, String)], Int), (String, String, Int)](('list, 'size) -> ('id1, 'id2, 'size)) {
  case (list, size) => list.map(record => (record._1, record._2, size))
}
.write(Tsv(args("output")))

但如果您的系统没有足够的内存,则必须使用昂贵的连接。

注: 您可以使用Tsv而不是TextLine,然后使用mapTo和拆分。