如何在spark中使用应用的cogroup方法和功能操作?

时间:2017-02-20 13:05:52

标签: scala apache-spark functional-programming

我已尝试解决已应用的cogroup问题。但我真的不知道......

如果有两个具有不同密钥的RDD,如下例所示,是否可以仅在使用data1的第一个单词相同时提取有效cogroup

val data1 = sc.parallelize(Seq(("aa", 1), ("ba", 2), ("bc", 2), ("b", 3), ("c", 1)))
val data2 = sc.parallelize(Seq(("a", 3), ("b", 5)))

val cogroupRdd: RDD[(String, (Iterable[Int], Iterable[Int]))] = data1.cogroup(data2)
/* List(
    (ba,(CompactBuffer(2),CompactBuffer())), 
    (bc,(CompactBuffer(2),CompactBuffer())), 
    (a,(CompactBuffer(),CompactBuffer(3))), 
    (b,(CompactBuffer(3),CompactBuffer(5))), 
    (c,(CompactBuffer(1),CompactBuffer())), 
    (aa,(CompactBuffer(1),CompactBuffer()))
) */

结果应为Array(("aa", 1), ("ba", 2), ("bc", 2), ("b", 3))

我使用broadcast()解决了这个问题,因为@mrsrinivas说。 但broadcast()不适合大数据。

val bcast = sc.broadcast(data2.map(_._1).collect())
val result = data1.filter(r => bcast.value.contains(myFuncOper(r._1)))

是否有使用cogroup功能操作解决此问题的方法?

2 个答案:

答案 0 :(得分:1)

您可以在提取与cogroup键匹配的密钥后使用data2,然后使用filtermap删除没有匹配的值和“重组”数据:

val result: RDD[(String, Int)] = data1
  .keyBy(_._1.substring(0, 1)) // key by first character
  .cogroup(data2)
  .filter { case (_, (_, data2Values)) => data2Values.nonEmpty }
  .flatMap { case (_, (data1Values, _)) => data1Values }

答案 1 :(得分:1)

<强>短

val result = data1
  .flatMap(x => x._1.split("").map(y => (y, x)))
  .join(data2)
  .map(x => x._2._1)
  .distinct

<强>详细说明:

flatMap(x => x._1.split("").map(y => (y, x)))持有

 List(
  (a, (aa, 1)),
  (a, (aa, 1)),
  (b, (ba, 2)),
  (a, (ba, 2)),
  (b, (bc, 2)),
  (c, (bc, 2)),
  (b, (b, 3)),
  (c, (c, 1))
)
join(data2)

之后

List(
  (a, ((aa, 1), 3)),
  (a, ((aa, 1), 3)),
  (a, ((ba, 2), 3)),
  (b, ((ba, 2), 5)),
  (b, ((bc, 2), 5)),
  (b, ((b, 3), 5))
)

现在我们所有人都对不同的第二对第一对感兴趣,可以通过map(x => x._2._1).distinct

来完成