首页 理论教育 属性图:定义多重图与编码顶点和边属性

属性图:定义多重图与编码顶点和边属性

时间:2026-01-23 理论教育 峰子 版权反馈
【摘要】:属性图是一个有向多重图,带有连接每个顶点和边的用户定义的对象。逻辑上的属性图对应于一对类型化的数据集合,这个集合对每一个顶点和边的属性进行编码。图4-7 属性图在GraphX项目中,假设构造一个包括不同合作者的属性图。实现了从RDD集合来生成属性图。graph.edges.filter{case Edge=>src>dst}.count除了属性图的顶点和边视图,GraphX也包含了一个三元组视图。SELECT src.id,dst.id,src.attr,e.attr,dst.attrFROM edges AS e LEFT JOIN vertices AS src,vertices AS dstON e.srcId=src.Id AND e.dstId=dst.Id或者通过图4-8所示内容来表示。

属性图(Property Graph)是一个有向多重图,带有连接每个顶点和边的用户定义的对象。有向多重图中并行的边共享相同的源和目的顶点。属性图支持并行边的能力简化了建模场景,这个场景中,一个顶点可能存在多种关系(例如同事之间可同时存在同事关系和朋友关系)。每个顶点由唯一的64位的标识符(VertexID)Key。GraphX并没有对顶点标识强加任何排序。同样,边拥有相应的源和目的顶点的标识符。

属性图通过Vertex(VD)和Edge(ED)属性进行参数化,这两个属性中的元素分别和图集合中的点和边一一对应。

在某些情况下,在相同的图形中,可能希望顶点拥有不同的属性类型。这可以通过继承完成。如将用户和产品建模成一个二分图,代码如【例4-16】所示。

例4-16】二分图建模示例。

class VertexProperty()

case class UserProperty(val name:String)extends VertexProperty

case class ProductProperty(val name:String,val price:Double)extends VertexProperty

//图也许会有这样的类型

var graph:Graph[VertexProperty,String]=null

和RDD一样,属性图是不可变的、分布式的、容错的。图的值或者结构的改变需要生成一个新的图来实现。注意,原始图的大部分都可以在新图中重用,以便减少这种固有的功能性数据结构的成本。执行者使用一系列顶点分区试探法来对图进行分区。如RDD样,图中的每个分区可以在发生故障的情况下被重新创建在不同的机器上。

逻辑上的属性图对应于一对类型化的数据集合(RDD),这个集合对每一个顶点和边的属性进行编码。因此,图类包含访问图中顶点和边的成员,也就是说可以通过图类操作边和点。图类代码如下。

图示

VertexRDD[VD]和EdgeRDD[ED]类分别继承和优化自RDD[(VertexID,VD)]和RDD [Edge[ED]]。VertexRDD[VD]和EdgeRDD[ED]都支持额外的功能来进行图计算和利用内部优化。属性图的一个例子如图4-7所示。

图示

图4-7 属性图

在GraphX项目中,假设构造一个包括不同合作者的属性图。顶点属性可能包含用户名和职业,可以用描述合作者之间关系的字符串标注边。所得的图形将具有下面代码的类型签名,也就是Graph[(用户名,职业),关系]。

val userGraph:Graph[(String,String),String]

有很多方式可以从一个原始文件、RDD来构造一个属性图。最一般的方法是利用Graph object。【例4-17】实现了从RDD集合来生成属性图(此处代码只是一个片段,如果想要运行请参考后面完整的例子)。

例4-17】属性图示例。

图示(https://www.xing528.com)

在上面的例子中用到了Edge样本类。边有一个srcId和dstId分别对应于源和目标顶点的标识符。另外,Edge类有一个attr成员用来存储边属性。

可以分别用graph.vertices和graph.edges成员将一个图解构为相应的顶点和边,如【例4-18】所示。

例4-18】图解构示例。

val graph:Graph[(String,String),String]

//计算所有博士后用户

graph.vertices.filter{case(id,(name,pos))=>pos=="postdoc"}.count

//计算所有"src>dst"的边

graph.edges.filter(e=>e.srcId>e.dstId).count

注意,graph.vertices返回一个VertexRDD[(String,String)],它继承于RDD[(VertexID, (String,String))]。所以可以用Scala的case表达式来解构这个元组。另一方面,graph.edges返回一个包含Edge[String]对象的EdgeRDD。也可以使用case类的类型构造器,代码如下。

graph.edges.filter{case Edge(src,dst,prop)=>src>dst}.count

除了属性图的顶点和边视图,GraphX也包含了一个三元组视图。三元组视图逻辑上将顶点和边的属性保存为一个RDD[EdgeTriplet[VD,ED]],它包含EdgeTriplet类的实例。可以通过如下的SQL表达式表示这个连接。

SELECT src.id,dst.id,src.attr,e.attr,dst.attr

FROM edges AS e LEFT JOIN vertices AS src,vertices AS dst

ON e.srcId=src.Id AND e.dstId=dst.Id

或者通过图4-8所示内容来表示。

图示

图4-8 三元组视图

EdgeTriplet类继承于Edge类,并且加入了srcAttr和dstAttr成员,这两个成员分别包含源和目的的属性。用一个三元组视图渲染字符串集合描述用户之间关系的代码如下。

图示

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈