一:图计算的作用
统一用户识别
求最短路径
社群发现
推荐算法(ALS)
二:什么是Graphx
GraphX 通过弹性分布式属性图扩展了 Sprak RDD。
在图计算中,基本的数据结构表达就是:G = (V,E,D) V = vertex (顶点或者节点) E = edge (边) D = data (权重)。
三:如何使用Graphx实现图计算
//使用图计算
object GraphTest{
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("graphx").master("local[4]").getOrCreate()
//1.创建测试数据
//创建点,通过本地集合创建RDD,因为Graphx本质上就是RDD
//(1, ("张三", 20))--> 1表示该点的id , ("张三", 20)表示该点的值
val vertices: RDD[(VertexId, (String, Int))] = spark.sparkContext.parallelize(Seq[(VertexId,(String,Int))](
(1, ("张三", 20)),
(2, ("李四", 20)),
(3, ("王五", 20)),
(4, ("赵六", 20)),
(5, ("韩梅梅", 20)),
(6, ("李雷", 20)),
(7, ("小明", 20)),
(9, ("tom", 20)),
(10, ("jerry", 20)),
(11, ("ession", 20))
))
//创建边,边实际上也是通过两个点建立的, Edge(1, 136,0) 0代表权重,这里不需要权重计算,这个参数也可以不写
// Edge(1, 136,0)--> 1表示该边的一个点,136也是这条边的另外一个点,0是权重
val edges: RDD[Edge[Int]] = spark.sparkContext.parallelize(Seq(
Edge(1, 136,0),
Edge(2, 136,0),
Edge(3, 136,0),
Edge(4, 136,0),
Edge(5, 136,0),
Edge(4, 158,0),
Edge(5, 158,0),
Edge(6, 158,0),
Edge(7, 158,0),
Edge(9, 188,0),
Edge(10, 188,0),
Edge(11, 188,0)
))
//使用Graphx创建图,注意参数的数据类(vertices,edges),写错会报错
val graph: Graph[(String, Int), Int] = Graph(vertices,edges)
//1.查看点
/*
(158,null)
(11,(ession,20))
(1,(张三,20))
(4,(赵六,20))
(9,(tom,20))
(3,(王五,20))
(6,(李雷,20))
(7,(小明,20))
(5,(韩梅梅,20))
(188,null)
(10,(jerry,20))
(136,null)
(2,(李四,20))
*/
// graph.vertices.foreach(println(_))
//查看边
/*
Edge(1,136,0)
Edge(9,188,0)
Edge(10,188,0)
Edge(5,158,0)
Edge(4,136,0)
Edge(4,158,0)
Edge(6,158,0)
Edge(11,188,0)
Edge(2,136,0)
Edge(3,136,0)
Edge(7,158,0)
Edge(5,136,0)
*/
//graph.edges.foreach(println(_))
//划分整个图,划分成每个可以联通的小图
val connect: Graph[VertexId, Int] = graph.connectedComponents()
//遍历连通图的点
//connect.vertices.foreach(println(_))
/*
(11,9)
(158,1)
(1,1)
(4,1)
(9,9)
(6,1)
(3,1)
(10,9)
(188,9)
(2,1)
(5,1)
(7,1)
(136,1)
从结果中可以看出,一共划分为两个图,每个图以最小的id为中心聚合(?,1)(?,9)
第一个图的最小id = 1, 第二个图的最小id = 9
*/
//最终需求 数据格式 : (id,(id,(name,age)))
//获取联通图的所有点 和 联通之前的所有点进行聚合
val rdd: RDD[(VertexId, (VertexId, (String, Int)))] = connect.vertices.join(vertices)
//进行
val result: RDD[(VertexId, Iterable[(VertexId, String, Int)])] = rdd.map {
case (id, (aggid, (name, age))) => (aggid, (id, name, age))
}.groupByKey()
result.foreach(println(_))
//最终结果
//(1,CompactBuffer((4,赵六,20), (1,张三,20), (5,韩梅梅,20), (6,李雷,20), (2,李四,20), (3,王五,20), (7,小明,20)))
//(9,CompactBuffer((9,tom,20), (10,jerry,20), (11,ession,20)))
}
}
注意:
1.创建点的时候数据类型val vertices: RDD[(VertexId, (String, Int))]
2.创建边的数据类型 val edges: RDD[Edge[Int]]
写错就会报错