Scala Spark地图类型匹配问题

时间:2016-09-19 21:40:30

标签: scala apache-spark

我正在尝试使用Scala对日志数据执行一系列转换,而且我在匹配元组方面遇到了困难。我有一个包含用户ID,网址和日期的数据框。我可以将数据帧映射到RDD,并使用此映射按键减少:

val countsRDD = usersUrlsDays.map { case Row(date:java.sql.Date, user_id:Long, url:String) => Tuple2(Tuple2(user_id, url), 1) }.rdd.reduceByKey(_+_)

这给了我一个RDD((user_id,url),count):

scala> countsRDD.take(1)
res9: Array[((Long, String), Int)]     
scala> countsRDD.take(1)(0)
res10: ((Long, String), Int)

现在我想通过url反转它来产生:

(url, [(user_id, count), ...])

我试过这个:

val urlIndex = countsRDD.map{ case Row(((user_id:Long, url:String), count:Int)) => Tuple2(url, List(Tuple2(user_id, count))) }.reduceByKey(_++_)

这会产生匹配错误:

 scala.MatchError: ... (of class scala.Tuple2)

我已尝试使用显式和隐式类型对这两个地图调用进行了许多不同的排列,这似乎让我最远。我希望这里有人可以帮助我指出正确的方向。

1 个答案:

答案 0 :(得分:2)

这样的事情应该有效:

countsRDD
  .map{ case ((user_id, url), count) => (url, (user_id, count)) }
  .groupByKey
  • countsRDD RDD[((String, String), Int)]不是RDD[Row]
  • 无需使用TupleN。元组文字可以正常工作。
  • 由于countsRDD是静态类型的(与RDD[Row]不同),因此您不必指定类型。
  • 不要使用reduceByKey进行列表连接。这是您可以采取的最糟糕的方法,并忽略了计算复杂性,垃圾收集器和常识。 如果您确实需要分组数据,请使用专为其设计的操作。