【问题标题】:How to find intersection between a specific node and its neighbors in Spark GraphX with Scala如何使用 Scala 在 Spark GraphX 中查找特定节点与其邻居之间的交集
【发布时间】:2019-08-20 12:40:02
【问题描述】:

我是 spark graphx 的新手,并尝试分布式计算特定节点之间的交集,例如 ID = 1 的节点与其在 spark GraphX 中的邻居。

我已经使用 GraphLoader.edgeListFile(sc,"Path") 加载了边缘列表。然后我用 collectNeighborIds 找到节点 id = 1 的邻居 ID,并在其上执行映射函数以查找每个邻居邻居并计算与所选节点(ID = 1 的节点)邻居的交集。 这是代码。

val graph = GraphLoader.edgeListFile(sc,path to edgelist)
val node_collect_neighborsId1 = graph.collectNeighborIds(EdgeDirection.Either).filter(x=> x._1 == 1)

val node1_neighbors_ID=node_collect_neighborsId1.flatMap(x=> x._2)

def compute_intersection (vertex :VertexId) = {


  var node2_collect_neighborsId: RDD[(VertexId, Array[VertexId])] = graph.collectNeighborIds(EdgeDirection.Either).filter(x=> x._1 == vertex)

  var node2_neighbors_ID=node2_collect_neighborsId.flatMap(x=> x._2)

  var intersect_two_node = node1_neighbors_ID.intersection(node2_neighbors_ID)

  (vertex, intersect)

}

val result = node1_neighbors_ID.map(compute_intersection)

我希望在最后,结果变量应该包含包含顶点 id 的行,该顶点 id 是邻居的 id 和我们称之为交集的两组节点邻居之间的公共节点。但我不能打印它们,看看里面有什么。 请帮我解决计算交集和打印结果的问题

【问题讨论】:

  • 你能提供一些输入输出的例子吗?
  • 例如节点 1 有这个邻居 => (2,3,4,5) 并且每个节点都有自己的邻居,例如节点 2 有这个邻居 =>(3,5, 8)。数字是节点 ID。在这种情况下,节点 1 和 2 的交点将是 (3,5)。我想用 map 函数为所有邻居获取这个结果,并调用 compute_intersection 函数来计算它们并将它存储在结果变量中,它是一个 RDD。但我无法打印结果以查看其中的内容,并且我不确定我编写的代码是否正确
  • 我正在研究社区检测,其中一部分我需要获取一个节点与其邻居之间的相似性,为此,我需要获取所选节点与其邻居之间的交集.这是我遇到的问题

标签: scala apache-spark graph


【解决方案1】:

您无法构建RDD[RDD[T]] 类型的结果。因此,您不应该为 map 内的每个邻居计算交集。

您可以使用aggregateMessages 计算所有目标邻居的交集:

def computeIntersection[VD, ED](graph: Graph[VD, ED], targetVertexId: Long): VertexRDD[List[Long]] = {
  //mark the target's neighbors
  val verticesWithTargetNeighborFlag = graph.aggregateMessages[Boolean](
    triplet => {
      if(triplet.srcId == targetVertexId && triplet.dstId != targetVertexId) {
        triplet.sendToDst(true)
      } else if(triplet.dstId == targetVertexId && triplet.dstId != targetVertexId) {
        triplet.sendToSrc(true)
      }
    },
    (msg1, msg2) => msg1 || msg2,
    TripletFields.None
  )
  val graphWithTargetNeighborFlag = Graph(verticesWithTargetNeighborFlag, edges)
  //collect intersection vertices for each target's neighbor
  val verticesWithIntersection = graphWithTargetNeighborFlag.aggregateMessages[List[Long]](
    triplet => if (triplet.srcAttr && triplet.dstAttr) { //both are target's neighbors
      triplet.sendToDst(List(triplet.srcId))
      triplet.sendToSrc(List(triplet.dstId))
    },
    (msg1, msg2) => msg1 ::: msg2,
    TripletFields.All
  )
  verticesWithIntersection
}

你可以使用collect打印RDD元素:

rdd.collect().foreach(println)

【讨论】:

  • 非常感谢您的大力帮助。它解决了我的问题,
  • 我有我的最后一个问题:我对我的代码进行了一些更改并使用了广播变量并且它起作用了。但我不知道这段代码是否并行和分布式运行?代码如下所示: val brdcast = sc.broadcast(node_collect_neighborsId1.collect()) 而 compute_intersection 函数仅包含以下代码: var intersect_nodes = (brdcast.value.flatMap(x=> x._2).toSeq).intersect ((graph.collectNeighborIds(EdgeDirection.Either).filter(x=> x._1 == vertex).collect().flatMap(x=> x._2).toSeq)); (相交节点)。此代码是否以分布式方式运行?
  • 我的意思是通过使用collect和toSeq,代码是再次以分布式方式运行还是只是将所有内容收集到主节点而不以分布式方式运行?
  • 不,不是。 broadcast.value 是计划 scala 集合,而不是 rdd。此外,驱动程序上存在收集执行结果(它不分布在执行器上)。所以 brdcastValue.flatMap(collectResult) 只是一个 scala 集合转换,而不是并行执行。
  • 感谢您的完美回答。你真的帮我解决了这个问题。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
相关资源
最近更新 更多