基于Graphx/Spark的pyspark父子关系模型

基于Graphx/Spark的pyspark父子关系模型,pyspark,spark-graphx,Pyspark,Spark Graphx,我有一个包含(子、父)实体的数据集。我需要从数据集中找到每个孩子的最终父母。我的数据集有130万条记录。样本数据如下所示 c-1, p-1 p-1, p-2 p-2, p-3 p-3, p-4 在上述样本数据中,c-1的最终母体是p-4,p-1的最终母体是p-4,依此类推。 有时,为了找到孩子的最终父母,我需要递归地遍历多个级别。 这就是我迄今为止所尝试的 我试图创建一个spark DF,并试图递归地找到 每个孩子的父母。但这种方法需要很长时间 我试图创造 可应用于数据集每一行的自定义项。但我

我有一个包含(子、父)实体的数据集。我需要从数据集中找到每个孩子的最终父母。我的数据集有130万条记录。样本数据如下所示

c-1, p-1
p-1, p-2
p-2, p-3
p-3, p-4
在上述样本数据中,c-1的最终母体是p-4,p-1的最终母体是p-4,依此类推。 有时,为了找到孩子的最终父母,我需要递归地遍历多个级别。 这就是我迄今为止所尝试的

  • 我试图创建一个spark DF,并试图递归地找到 每个孩子的父母。但这种方法需要很长时间
  • 我试图创造 可应用于数据集每一行的自定义项。但我需要 在UDF中调用DF(查找数据集)。但spark没有 支持在UDF中使用DF。所以,即使是这种方法也帮不了我

  • 关于如何解决这个问题有什么建议吗?

    为了解决您提到的两个问题,在spark中使用Graphx Pregel API实现CTE可能会有帮助

    下面是一个示例代码

    //setup & call the pregel api
    def calcTopLevelHierarcy(vertexDF: DataFrame, edgeDF: DataFrame): RDD[(Any,(Int,Any,String,Int,Int))] = {
    
    // create the vertex RDD
    // primary key, root, path
    val verticesRDD = vertexDF
      .rdd
      .map{x=> (x.get(0),x.get(1) , x.get(2))}
      .map{ x => (MurmurHash3.stringHash(x._1.toString).toLong, ( x._1.asInstanceOf[Any], x._2.asInstanceOf[Any] , x._3.asInstanceOf[String]) ) }
    
    // create the edge RDD
    // top down relationship
    val EdgesRDD = edgeDF.rdd.map{x=> (x.get(0),x.get(1))}
      .map{ x => Edge(MurmurHash3.stringHash(x._1.toString).toLong,MurmurHash3.stringHash(x._2.toString).toLong,"topdown" )}
    
    // create graph
    val graph = Graph(verticesRDD, EdgesRDD).cache()
    
    val pathSeperator = """/"""
    
    // initialize id,level,root,path,iscyclic, isleaf
    val initialMsg = (0L,0,0.asInstanceOf[Any],List("dummy"),0,1)
    
    // add more dummy attributes to the vertices - id, level, root, path, isCyclic, existing value of current vertex to build path, isleaf, pk
    val initialGraph = graph.mapVertices((id, v) => (id,0,v._2,List(v._3),0,v._3,1,v._1) )
    
    val hrchyRDD = initialGraph.pregel(initialMsg,
      Int.MaxValue,
      EdgeDirection.Out)(
      setMsg,
      sendMsg,
      mergeMsg)
    
    
    // build the path from the list
    val hrchyOutRDD = hrchyRDD.vertices.map{case(id,v) => (v._8,(v._2,v._3,pathSeperator + v._4.reverse.mkString(pathSeperator),v._5, v._7 )) }
    
      hrchyOutRDD
    
    }
    
    在方法calcTopLevelHierarcy()中,您可以传入数据帧(这解决了您的第二点)

    下面是一个非常好的示例代码。请看一看

    希望,这有帮助