我有两个rdd一个rdd只有一列其他有两列加入两个RDD上的键我已经添加了虚拟值0,有没有其他有效的方法使用join这样做?
val lines = sc.textFile("ml-100k/u.data")
val movienamesfile = sc.textFile("Cml-100k/u.item")
val moviesid = lines.map(x => x.split("\t")).map(x => (x(1),0))
val test = moviesid.map(x => x._1)
val movienames = movienamesfile.map(x => x.split("\\|")).map(x => (x(0),x(1)))
val shit = movienames.join(moviesid).distinct()
修改:
让我在SQL中转换这个问题。比方说我有table1 (moveid)
和table2 (movieid,moviename)
。在SQL中我们写了类似的东西:
select moviename, movieid, count(1)
from table2 inner join table table1 on table1.movieid=table2.moveid
group by ....
这里的SQL table1
只有一列,其中table2
有两列,join
仍在工作,同样,Spark可以加入来自两个RDD的键。
答案 0 :(得分:8)
仅在PairwiseRDDs
上定义了连接操作,这与SQL中的关系/表完全不同。 PairwiseRDD
的每个元素都是Tuple2
,其中第一个元素是key
,第二个元素是value
。只要key
提供有意义的hashCode
如果您想在SQL-ish中考虑这一点,您可以考虑使用密钥,因为ON
子句和value
包含所选列的所有内容。
SELECT table1.value, table2.value
FROM table1 JOIN table2 ON table1.key = table2.key
虽然这些方法乍一看看起来很相似,但你可以用另一种表达方法,但有一个根本区别。当您查看SQL表并忽略约束时,所有列都属于同一对象类,而key
中的value
和PairwiseRDD
具有明确的含义。
回到您的问题以使用join
,您需要key
和value
。可以说比使用0
作为占位符更清洁的是使用null
单例,但实际上没有办法绕过它。
对于小数据,您可以使用与广播连接类似的方式使用过滤器:
val moviesidBD = sc.broadcast(
lines.map(x => x.split("\t")).map(_.head).collect.toSet)
movienames.filter{case (id, _) => moviesidBD.value contains id}
但如果您真的想要SQL-ish加入,那么您应该只使用SparkSQL。
val movieIdsDf = lines
.map(x => x.split("\t"))
.map(a => Tuple1(a.head))
.toDF("id")
val movienamesDf = movienames.toDF("id", "name")
// Add optional join type qualifier
movienamesDf.join(movieIdsDf, movieIdsDf("id") <=> movienamesDf("id"))