Spark多重联接

时间:2015-06-02 07:55:35

标签: apache-spark

使用spark上下文,我想在它们之间执行多个连接 rdd's,其中要加入的rdd的数量应该是动态的。 我希望结果展开,例如:

val rdd1  = sc.parallelize(List((1,1.0),(11,11.0), (111,111.0)))
val rdd2  = sc.parallelize(List((1,2.0),(11,12.0), (111,112.0)))
val rdd3  = sc.parallelize(List((1,3.0),(11,13.0), (111,113.0)))
val rdd4  = sc.parallelize(List((1,4.0),(11,14.0), (111,114.0)))
val rdd11 = rdd1.join(rdd2).join(rdd3).join(rdd4)
.foreach(println)

生成以下输出:

(11,(((11.0,12.0),13.0),14.0))

(111,(((111.0,112.0),113.0),114.0))

(1,(((1.0,2.0),3.0),4.0))

我想:

  1. 展开数值,例如第一行应为: (11,11.0,12.0,13.0,14.0)。

  2. 动态执行此操作,以便它可以处理任何动态数字 rdd的加入。

  3. 任何想法都会受到赞赏,

    利。

2 个答案:

答案 0 :(得分:2)

我不会使用join,而是使用union后跟groupByKey来实现您的目标。

这是我要做的 -

val emptyRdd = sc.emptyRDD[(Int, Double)]
val listRdds = List(rdd1, rdd2, rdd3, rdd4) // satisfy your dynamic number of rdds
val unioned = listRdds.fold(emptyRdd)(_.union(_))
val grouped = unioned.groupByKey
grouped.collect().foreach(println(_))

这将产生结果:

(1,CompactBuffer(1.0, 2.0, 3.0, 4.0))
(11,CompactBuffer(11.0, 12.0, 13.0, 14.0))
(111,CompactBuffer(111.0, 112.0, 113.0, 114.0))

<强>更新

如果您仍想使用join,这是如何使用有些复杂的foldLeft函数来完成的 -

val joined = rddList match {
  case head::tail => tail.foldLeft(head.mapValues(Array(_)))(_.join(_).mapValues {
    case (arr: Array[Double], d: Double) => arr :+ d
  })
  case Nil => sc.emptyRDD[(Int, Array[Double])]
}

joined.collect将产生

res14: Array[(Int, Array[Double])] = Array((1,Array(1.0, 2.0, 3.0, 4.0)), (11,Array(11.0, 12.0, 13.0, 14.0)), (111,Array(111.0, 112.0, 113.0, 114.0)))

答案 1 :(得分:0)

遇到此问题的其他人可能会发现groupWith有帮助。来自文档:

>>> w = sc.parallelize([("a", 5), ("b", 6)])
>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2)])
>>> z = sc.parallelize([("b", 42)])
>>> [(x, tuple(map(list, y))) for x, y in sorted(list(w.groupWith(x, y, z).collect()))]
[('a', ([5], [1], [2], [])), ('b', ([6], [4], [], [42]))]