Graphx处理janusGraph数据实现

该博客提出在spark直接执行gremlinSQL方案受阻时的备选方案。将gremlinSql查询结果转化为startGraph并转写到HDFS,spark读取其构建graphx可用的图,调用graphx图计算算法,实现graphX操作janusgraph,还介绍了结果转json及读取转换的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明: 此方案是在spark直接执行gremlinSQL方案实现受阻的情况下的备选方案,不涉及工作机密,不存在泄密可能,纯属个人思考,希望抛砖引玉

方案: 将gremlinSql的查询结果转化为startGraph,然后转写到HDFS,spark读取hdfs的starGraphJSon构建graphx可用的图,然后就可以调用graphx丰富的图计算算法;从而将实现graphX操作janusgraph的目的

1. gremlinSql的查询结果转换成starGraphJson

由于org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter保存的graphSon格式无法满足需求,所以将查询出的带path的点边数据自己转换成单点图的json结构,转化方法如下,然后存到hdfs,存储方法不再赘述。

public StringBuilder generatorStarGraphJson(Vertex vertex, Edge edge, StringBuilder starGraphJson){
	String inVId;
	String outVId;
	String VId;
	starGraphJson.append("{").append("\"id\":"+vertex.id()+","+"\"label\":\""+vertex.label()+"\",");
	//这种情况有outE和inE,outE中会有inV信息,inE会有一个inV
	inVId = edge.inVertex().id().toString();
	outVId = edge.outVertex().id().toString();
	VId = vertex.id().toString();
	if(inVId.equalsIgnoreCase(VId)){
		starGraphJson.append("\"outE\":{").append("\""+edge.label()+"\":[{").append("\"id\":\""+edge.id()+"\",")
				.append("\"inV\":"+edge.inVertex().id()+",").append("\"properties\":{"+concatEdgeProperties(edge)+"}}]},");
	}else if(outVId.equalsIgnoreCase(VId)){
		starGraphJson.append("\"inE\":{").append("\""+edge.label()+"\":[{").append("\"id\":\""+edge.id()+"\",")
				.append("\"outV\":"+edge.inVertex().id()+",").append("\"properties\":{"+concatEdgeProperties(edge)+"}}]},");
	}else{
		throw new Exception("点边不对应数据错误!!!");
	}
	//拼接点的properties
	starGraphJson.append("\"properties\":{").append(concatVertexProperties(vertex)).append("}}");
	return  starGraphJson;
}

2. spark读取指定路径的starGraph转成graph

class GraphSon2GraphXRDD() extends Serializable {

def getGraphConf(HDFSFilePath : String): BaseConfiguration ={ val inputGraphConf = new BaseConfiguration inputGraphConf.setProperty("gremlin.graph", classOf\[HadoopGraph\].getName) inputGraphConf.setProperty(Constants.GREMLIN\_HADOOP\_GRAPH\_READER, classOf\[GraphSONInputFormat\].getName) inputGraphConf.setProperty(Constants.GREMLIN\_HADOOP\_INPUT\_LOCATION, HDFSFilePath) inputGraphConf.setProperty(Constants.MAPREDUCE\_INPUT\_FILEINPUTFORMAT_INPUTDIR, HDFSFilePath) inputGraphConf }

def getSc(sparkHost:String ,isRemote:Boolean): SparkContext ={ var sparkConf = new SparkConf() if(isRemote){ //待完善 }else{ sparkConf.setMaster("local\[*\]").setAppName("GraphSon2GraphX") } val sc = new SparkContext(sparkConf) sc }

def getJavaRDD(conf : BaseConfiguration, sc : SparkContext): JavaPairRDD\[AnyRef, VertexWritable\] ={ val jsc = JavaSparkContext.fromSparkContext(sc) val graphRDDInput = new InputFormatRDD val vertexWritableJavaPairRDD = graphRDDInput.readGraphRDD(conf, jsc) vertexWritableJavaPairRDD }

def getVertexRDD(vertexWritableJavaPairRDD : JavaPairRDD\[AnyRef, VertexWritable\]): RDD\[(Long,util.HashMap\[String,java.io.Serializable\])\] ={ vertexWritableJavaPairRDD.rdd.map((tuple2: Tuple2\[AnyRef, VertexWritable\]) => { // Get the center vertex val v = tuple2._2.get val g = StarGraph.of(v) // In case the vertex id in TinkerGraph is not long type // val vid = convertStringIDToLongID([v.id](http://v.id)().toString) val vid = [v.id](http://v.id)().toString.toLong // Pass the vertex properties to GraphX vertex value map and remain the original vertex id var graphxValueMap : util.HashMap\[String,java.io.Serializable\] = new util.HashMapString,java.io.Serializable graphxValueMap.put("originalID",[v.id](http://v.id)().toString) graphxValueMap.putAll(g.traversal.V([v.id](http://v.id)).valueMap().next(1).get(0)) (vid,graphxValueMap) }) }

def getEdgeRDD(vertexWritableJavaPairRDD : JavaPairRDD\[AnyRef, VertexWritable\]): RDD\[graphx.Edge\[util.HashMap\[String, java.io.Serializable\]\]\] ={ val edge = vertexWritableJavaPairRDD.rdd.flatMap((tuple2: Tuple2\[AnyRef, VertexWritable\]) => { val v = tuple2._2.get val g = StarGraph.of(v) val edgelist:util.List\[Edge\] = g.traversal.V([v.id](http://v.id)).outE().toList

  // Put all edges of the center vertex into the list
  val list = new collection.mutable.ArrayBuffer[graphx.Edge[util.HashMap[String,java.io.Serializable]]]()
  var x = 0
  for(x <- 0 until edgelist.size()){
    var srcId = edgelist.get(x).inVertex.id().toString
    var dstId = edgelist.get(x).outVertex.id().toString
    //        val md1 = convertStringIDToLongID(srcId)
    //        val md2 = convertStringIDToLongID(dstId)
    val md1 = srcId.toLong
    val md2 = dstId.toLong
    // Get the properties of the edge
    var edgeAttr = new util.HashMap[String,java.io.Serializable]()
    var perporties : util.Iterator[Property[Nothing]] = edgelist.get(x).properties()
    while(perporties.hasNext){
      val property = perporties.next()
      edgeAttr.put(property.key(),property.value().toString)
    }
    list.append(graphx.Edge(md1,md2,edgeAttr))
  }
  list
})
val edgeRDD = edge.distinct()
edgeRDD

}

def doLAP(vertexWritableJavaPairRDD : JavaPairRDD\[AnyRef, VertexWritable\], iterationNum : Int): Array\[Array\[String\]\] = { val vertexRDD = getVertexRDD(vertexWritableJavaPairRDD)

val edgeRDD = getEdgeRDD(vertexWritableJavaPairRDD)

val graph = graphx.Graph[util.HashMap[String,java.io.Serializable],
  util.HashMap[String,java.io.Serializable]](vertexRDD,edgeRDD,new util.HashMap[String,java.io.Serializable]())

val LVMRsult = lib.LabelPropagation.run(graph , iterationNum).vertices.collect.sortWith (_._1 < _._1).map(f => {
  println(f.toString())
  f})
getFinalCommunit(LVMRsult)

}

def getFinalCommunit(LVMRsult:Array\[(Long,Long)\]): Array\[Array\[String\]\] ={ var result = new Array[Array\[String\]](LVMRsult.length) var tmp = new ArrayBufferString for(i <- 0 until LVMRsult.length){ var k = 0 val array = new ArrayBufferString
  //社区中包含多个值
  for(j &lt;- (i+1) until LVMRsult.length) {
    if(LVMRsult(i)._2.equals(LVMRsult(j)._2)){
      if(!tmp.contains(LVMRsult(i)._1.toString)){
        array += LVMRsult(i)._1.toString
        tmp += LVMRsult(i)._1.toString
      }
      if(!tmp.contains(LVMRsult(j)._1.toString)){
        array += LVMRsult(j)._1.toString
        tmp += LVMRsult(j)._1.toString
      }
      k = k+1
    }
  }

  //自己为一个社区
  if(k.equals(0)){
    if(!tmp.contains(LVMRsult(i)._1.toString)){
      array += LVMRsult(i)._1.toString
      tmp += LVMRsult(i)._1.toString
    }

  }
  if(array.length &gt; 0){
    result.update(i,array.toArray.distinct)
  }
}
result.filter(f =&gt; {
  println(if (f.length &gt;0) f.mkString("(",",",")"))
  f != null
})

}

def doPageRank(vertexWritableJavaPairRDD : JavaPairRDD\[AnyRef, VertexWritable\], stopThreshold : Double): Array\[Array\[Any\]\] = { val vertexRDD:RDD\[(Long,util.HashMap\[String,java.io.Serializable\])\] = getVertexRDD(vertexWritableJavaPairRDD)


val edgeRDD = getEdgeRDD(vertexWritableJavaPairRDD)

val graph = graphx.Graph[util.HashMap[String,java.io.Serializable],
  util.HashMap[String,java.io.Serializable]](vertexRDD,edgeRDD,new util.HashMap[String,java.io.Serializable]())
val gpgraph = graph.pageRank(stopThreshold).cache()

val titleAndPrGraph = graph.outerJoinVertices(gpgraph.vertices) {
  (v, title, rank) =&gt; (rank.getOrElse(0.0), title)
}

//倒序 false  正序 true

// titleAndPrGraph.vertices.sortBy((entry: (VertexId, (Double, Object))) => entry.\_2.\_1, false).foreach(f => println(f.\_1+":"+f.\_2._1))

val pageRank = titleAndPrGraph.vertices.sortBy((entry: (VertexId, (Double, Object))) =&gt; entry._2._1, false).map(f =&gt; {
  println(f._1+":"+f._2._1)
  Array(f._1.toString,f._2._1)
})
pageRank.collect()

}

}

这样就贯通了janusgraph和graphx,调用graphx的丰富的图计算功能就畅通无阻,就是实现有点挫,希望抛砖引玉

转载于:https://my.oschina.net/zhouwang93/blog/3052345

### 图处理在 PySpark 中的替代方案 虽然 PySpark 的 GraphX 模块提供了图处理功能,但在 Python API 中其支持相对有限。对于需要更强大图处理能力的用户,可以考虑以下替代方案: #### 1. NetworkX NetworkX 是一个用于创建、操作和研究复杂网络结构的 Python 库。它支持丰富的图算法,包括最短路径、连通性分析、中心性计算等。NetworkX 的优势在于其简单易用的 API 和对小型图数据的高效处理能力。 ```python import networkx as nx # 创建有向图 G = nx.DiGraph() # 添加带权重的边 G.add_edge('A', 'B', weight=4) G.add_edge('B', 'C', weight=5) # 计算最短路径 shortest_path = nx.shortest_path(G, source='A', target='C', weight='weight') print(shortest_path) ``` NetworkX 适用于单机处理场景,若需处理大规模分布式图数据,则需结合其他工具。 #### 2. GraphFrames GraphFrames 是基于 PySpark DataFrame 构建的图处理库,提供了与 GraphX 类似的功能,但更易于使用,并且与 Spark SQL 集成良好。GraphFrames 支持多种图算法,如 PageRank、连通组件、三角形计数等,并且可以运行在 Spark 集群上,具备良好的扩展性。 ```python from graphframes import GraphFrame # 定义顶点和边的 DataFrame vertices = spark.createDataFrame([ ("A", "Alice", 34), ("B", "Bob", 36), ("C", "Charlie", 30) ], ["id", "name", "age"]) edges = spark.createDataFrame([ ("A", "B", "friend"), ("B", "C", "follow"), ("C", "A", "follow") ], ["src", "dst", "relationship"]) # 构建图并计算 PageRank g = GraphFrame(vertices, edges) results = g.pageRank(resetProbability=0.15, maxIter=10) results.vertices.select("id", "pagerank").show() ``` GraphFrames 的优势在于其与 Spark 生态系统的无缝集成,使得图数据可以轻松地与机器学习、流处理等模块结合使用。 #### 3. 使用 Neo4j + Spark 连接器 Neo4j 是一个高性能的图数据库,支持复杂的图查询语言 Cypher,并提供丰富的图算法库。通过 Neo4j 的 Spark 连接器,可以在 Spark 中读取和写入 Neo4j 数据库中的图数据,从而实现大规模图分析。 ```python # 从 Neo4j 读取图数据 neo4j_df = spark.read \ .format("org.neo4j.spark.DataSource") \ .option("url", "bolt://localhost:7687") \ .option("authentication.type", "basic") \ .option("authentication.basic.username", "neo4j") \ .option("authentication.basic.password", "password") \ .option("query", "MATCH (n)-[r]->(m) RETURN n, r, m") \ .load() # 执行 Spark SQL 查询 neo4j_df.createOrReplaceTempView("graph") result = spark.sql("SELECT * FROM graph LIMIT 10") result.show() ``` Neo4j 提供了图算法库(Graph Data Science Library),可以用于执行社区检测、路径查找、节点嵌入等任务,适合企业级图分析需求。 #### 4. 使用 Apache TinkerPop + Gremlin Apache TinkerPop 是一个图计算框架,支持多种图数据库(如 Neo4j、JanusGraph、Amazon Neptune)并通过 Gremlin 查询语言进行图操作。通过 Gremlin-Python 可以在 Python 中编写图查询逻辑,并与 Spark 集成进行分布式处理。 ```python from gremlin_python import statics from gremlin_python.structure.graph import Graph from gremlin_python.process.graph_traversal import __ from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection graph = Graph() g = graph.traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g')) # 查询所有边 edges = g.E().toList() print(edges) # 查询从 A 到 B 的路径 paths = g.V().has('name', 'Alice').repeat(out()).until(has('name', 'Charlie')).path().by('name').toList() print(paths) ``` TinkerPop 提供了与 Spark 集成的 Gremlin OLAP 模式,可以利用 Spark 的分布式计算能力执行图遍历和分析任务。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值