关系数据为 from -> to 的 边
设定数据格式为Long
spark计算关系网络 由于数据量过大 某些算法无法实现或实现代价太大
为了降低计算压力或优化计算方法 将整个关系网络中的孤立的,不与其他节点相连的数据关系区分出来,形成一个个小的关系网络图
实现方法:
( 用 图id 来标识每个关系网络图)
初始状态下 不知道每个节点所属网络图
将每个节点的 id 设为他自己所在网络的 图id(Long)
通过groupBykey() 聚合方法 找到节点所有的连通的节点(只包含自己的图)
将所有的图中 ,图id最小的(也可以最大,用来防止死循环)一个 图id 设为自己的图id
可以获得一个 (节点id ,图id )的 节点所属关系网络图 数据集
将该数据集通过 join 的方式赋给原始的关系数据
得到数据结构为 (from:Long, 图id_1 :Long )-> (to : Long , 图id_2 : Long) 的新的关系数据
过滤出其中: 图id_1 != 图id_2 的数据 进行下一次迭代
多次迭代后,每个节点的 图id 为该节点所在关系网络图中节点id最小的值,该值即为节点所属关系网络图的图id
代码实现:
val edgerdd = **** // (from ,to)结构的关系数据,无向图
var graphIdRdd = edgerdd.reduceByKey((a, b) => if (a < b) a else b)
.map(a=>if (a._1<a._2) (a._1,a._1) else a) //compare with itself
graphIdRdd.count()
var count = 1
while (count != 0) {
//give nodeid a graphid
val edge_rdd_need_deal = edgerdd.leftOuterJoin(graphIdRdd) //give fromnode a graphId
.map(a => {
val from = a._1
val to = a._2._1
val fromgraphId = a._2._2.get
(to, (from, fromgraphId))
})
.leftOuterJoin(graphIdRdd) //give tonode a graphId
.map(a => {
val to = a._1
val from_graphId = a._2._1
val tographId = a._2._2.get
(from_graphId, tographId)
})
.filter(a => a._1._2 != a._2) // filter the relation which is not changed
count = edge_rdd_need_deal.count().toInt
val new_graphIdRdd = edge_rdd_need_deal
.reduceByKey((a, b) => if (a < b) a else b) //get the neighbors' min graphid
.map(a => {
val from = a._1._1
val from_graphId = a._1._2
val new_graphId = a._2
(from, if (from_graphId < new_graphId) from_graphId else new_graphId)
}) // get the new graphid ,small than the old one
new_graphIdRdd.count()
// union the don't be changed node
graphIdRdd = graphIdRdd.union(new_graphIdRdd).reduceByKey((a, b) => if (a < b) a else b).repartition(300)
graphIdRdd.count()
}
println("all is ok")
(根据需要来缓存数据)
仅供参考