目录
一、基本概念
(一)图(graph)
1、定义:
图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种数据结构。通常表示为二元组:Graph=(V,E),可以对事物之间的关系建模。
2、应用场景:
在地图应用中寻找最短路径。
社交网络关系。
网页间超链接关系。
(二)Spark GraphX
1、简介:
Spark GpaphX是一个分布式图处理框架,基于spark平台提供对图计算和图挖掘简洁易用而丰富多彩的接口,极大地方便了分布式图处理的需求;
2、特点:
基于内存实现了数据的复用与快速读取。
通过弹性分布式属性图(Property Graph)统一了图视图与表视图。
与Spark Streaming、Spark SQL和Spark MLlib等无缝衔接。
3、核心抽象:
弹性分布式属性图(Resilient Distributed Property Graph);
顶点和边都带属性的有向多重图。
一份物理存储,两种视图。
注:对Graph视图的所有操作,最终都会转换成其关联的Table视图的RDD操作来完成
4、Spark GraphX中有三个重要的概念:
(1)Vertices:对应的RDD名称为VertexRDD,属性包括顶点ID和顶点属性;
(2)Edges:对应的RDD名称为EdgeRDD,属性包括源顶点ID、目标顶点ID、边属性;
(3)Triplets:属性包括源顶点ID、源顶点属性、边属性、目标顶点ID、目标顶点属性;
5、度(Degree):
在Spark GraphX中把Degree分为inDegrees(每个顶点入度)、outDegrees(每个顶点的出度)、degrees(每个顶点的度);
二、图例说明
1、顶点5的属性为(franklin,professor);
2、顶点5到顶点3的边属性为Advisor,此边的源id为5,目的id为3;
3、顶点5的入度为1、出度为2、度为3;
三、图例代码
package com.dt.spark.graphx.test
import org.apache.log4j.{Level, Logger}
import org.apache.spark.graphx.{Edge, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.SparkSession
object Graphx_test {
def main(args: Array[String]): Unit = {
/**
* 设置日志输出级别
*/
Logger.getLogger("org").setLevel(Level.ERROR)
val spark: SparkSession = SparkSession.builder().appName("test GraphX").master("local[*]").getOrCreate()
val sc: SparkContext = spark.sparkContext
/**
* 手动创建图graphX
*/
//创建顶点rdd
val usersRdd: RDD[(Long, (String, String))] = sc.parallelize(Array((3L, ("rxin", "student")), (7L, ("jgonzal", "postdoc")),
(5L, ("franklin", "prof")), (2L, ("istoica", "prof"))))
//创建边的rdd pi:项目负责人
val edgesRdd: RDD[Edge[String]] = sc.parallelize(Array(Edge(3L, 7L, "collab"), Edge(5L, 3L, "advisor"),
Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))
// 定义案例中顶点的默认使用者,在缺失使用者的情况,图可以建立关联
val defaultUser = ("tom", "Missing")
//创建图
val graph: Graph[(String, String), String] = Graph(usersRdd, edgesRdd, defaultUser)
/**
* 打印出所有的triplets
*/
println("===========打印出所有的triplets===========")
graph.triplets.collect().foreach(v => println(v))
println("===========打印出所有的vertices===========")
graph.vertices.collect().foreach(v => println(v))
println("===========打印出所有的edges===========")
graph.edges.collect().foreach(v => println(v))
/**
* 打印每个顶点的入度、出度、度
*/
println("===========入度===========")
graph.inDegrees.collect().foreach(v => println(v))
println("===========出度===========")
graph.outDegrees.collect().foreach(v => println(v))
println("===========度===========")
graph.degrees.collect().foreach(v => println(v))
/**
* 找出职位为教授prof的人员
*/
println("===========找出职位为教授prof的人员===========")
graph.vertices.filter {
case (id, (name, pos)) => pos == "prof"
}.collect().foreach(v => println(v))
/**
* 找出源节点id小于目标节点id的所有边
*/
println("===========找出源节点id小于目标节点id的所有边===========")
graph.edges.filter(e => e.srcId < e.dstId)
.collect().foreach(v => println(v))
spark.close()
}
}
===========打印出所有的triplets===========
((3,(rxin,student)),(7,(jgonzal,postdoc)),collab)
((5,(franklin,prof)),(3,(rxin,student)),advisor)
((2,(istoica,prof)),(5,(franklin,prof)),colleague)
((5,(franklin,prof)),(7,(jgonzal,postdoc)),pi)
===========打印出所有的vertices===========
(2,(istoica,prof))
(3,(rxin,student))
(5,(franklin,prof))
(7,(jgonzal,postdoc))
===========打印出所有的edges===========
Edge(3,7,collab)
Edge(5,3,advisor)
Edge(2,5,colleague)
Edge(5,7,pi)
===========入度===========
(3,1)
(5,1)
(7,2)
===========出度===========
(2,1)
(3,1)
(5,2)
===========度===========
(2,1)
(3,2)
(5,3)
(7,2)
===========找出职位为教授prof的人员===========
(2,(istoica,prof))
(5,(franklin,prof))
===========找出源节点id小于目标节点id的所有边===========
Edge(3,7,collab)
Edge(2,5,colleague)
Edge(5,7,pi)