加入多个rdds

时间:2015-12-18 13:04:31

标签: scala apache-spark rdd

我有4个类型的RDD :((int,int,int),values),我的rdds是

rdd1: ((a,b,c), value) 
rdd2:((a,d,e),valueA) 
rdd3:((f,b,g),valueB)
rdd4:((h,i,c),valueC) 

我如何加入rdd,如rdd1加入rdd2加入rdd1加入rdd2 on“b”和rdd1加入rdd3加入“c”

所以Scala中的输出是finalRdd: ((a,b,c),valueA,valueB,valueC,value))

我尝试使用collectAsMap执行此操作,但它不能正常工作并抛出异常

代码仅适用于rdd1 join rdd2

val newrdd2=rdd2.map{case( (a,b,c),d)=>(a,d)}.collectAsMap
val joined=rdd1.map{case( (a,b,c),d)=>(newrdd2.get(a).get,b,c,d)} 

示例

rdd1: ((1,2,3),animals)
rdd2:((1,anyInt,anyInt),cat)
rdd3:((anyInt,2,anyInt),cow )
rdd 4: ((anyInt,anyInt,3),parrot)

输出应为((1,2,3),animals,cat,cow,parrot )

1 个答案:

答案 0 :(得分:1)

在RDD上有一个方便的join方法,但您需要使用特定的连接键来键入它,这是Spark用于分区和混洗的方法。

来自the docs

  

join(otherDataset,[numTasks]):当调用类型为(K,V)和(K,W)的数据集时,返回(K,(V,W))对的数据集以及所有元素对每把钥匙。通过leftOuterJoin,rightOuterJoin和fullOuterJoin支持外连接。

我无法编译我所处的位置,但手动它会是这样的:

val rdd1KeyA = rdd1.map(x => (x._1._1, (x._1._2, x._1._3. x._2) // RDD(a, (b,c,value))
val rdd2KeyA = rdd2.map(x => (x._1._1, x._2) // RDD(a, valueA)
val joined1 = rdd1KeyA.join(rdd2KeyA) // RDD(a, ((b,c,value), valueA))

val rdd3KeyB = rdd3.map(x => (x._1._2, x._2) // RDD(b, valueB)
val joined1KeyB = joined1.map(x => (x._2._1._1, (x._1, x._2._1._2, x._2._1._3. x._2._2) // RDD(b, (a, c, value, valueA))
val joined2 = joined1KeyB.join(rdd3keyB) // RDD(b, ((a, c, value, valueA), valueB))

......等等

避免collect*函数,因为它们不使用数据的分布式特性,并且容易在大负载上失败,它们将RDD上的所有数据混合到主节点上的内存中集合,可能正在吹一切都好了。