Hadoop层次结构难题

时间:2016-06-12 09:43:53

标签: sql hadoop apache-spark hive apache-pig

我最近开始研究Hadoop,我过去的经验是在ETL上。 现在我有一个问题,我想建立父子层次结构。 以下是输入 - 的 INPUT

Parent_Id Child_Id

FAC001    FAC001

FAC001    FAC002

FAC002    FAC003

FAC003    FAC004

FAC004    FAC005

AAA005    AAA005 

AAA005    AAA001 

AAA001    AAA006 

所需输出

Top_Parent_Id Parent_Id Child_Id Level

FAC001        FAC001    FAC001   1

FAC001        FAC001    FAC002   2

FAC001        FAC002    FAC003   3

FAC001        FAC003    FAC004   4

FAC001        FAC004    FAC005   5

AAA005        AAA005    AAA005   1

AAA005        AAA005    AAA006   2

你能否提出一个实现这个目标的方法,我已经在hive中实现了相同的逻辑,我可以将层次结构创建为预定义的级别(使用自联接)。 但我想知道是否可以在Spark或Pig中实现相同的动态级别。

注意:父母不一定要以数字或字母顺序小于Child,因此应避免订购。
感谢所有投入。

提前致谢。

1 个答案:

答案 0 :(得分:0)

这实际上是关于图表查询的问题。给你一个图形(一个分层树,或一系列树,在你的第一个表中,给出一个树的有向边),你想要一定深度的所有路径。这个查询很容易在图形框架中表达,这是Spark 1.6中的第三方软件包。我会谷歌的例子(现在不能做,我在火车上)。但实质上,任何重复自连接的查询都是图中的查询。

编辑:我回到家中,这是一个代码示例,可以处理您的数据,并从层次结构的顶部开始查找深度为4的顶点(但是,您必须定义一个主题和每个深度/级别的查询分别):

import org.graphframes._

// define a DataFrame of vertices - one of the columns must be "id"
val vertices = sqlContext.createDataFrame(Seq(
  ("FAC001", 1),
  ("FAC002", 1),
  ("FAC003", 1),
  ("FAC004", 1),
  ("FAC005", 1),
  ("AAA001", 1),
  ("AAA005", 1),
  ("AAA006", 1)
)).toDF("id", "some_attribute")

// define a DataFrame of edges - two columns must be "src" and "dst"
val edges = sqlContext.createDataFrame(Seq(
("FAC001", "FAC002"),
("FAC002", "FAC003"),
("FAC003", "FAC004"),
("FAC004", "FAC005"),
("AAA005", "AAA001"),
("AAA001", "AAA006")
)).toDF("src", "dst")

// define a GraphFrame
val hg = GraphFrame(vertices, edges)

// roots are those vertices which have no inDegree (only outDegrees)
val roots = vertices.select("id").except(hg.inDegrees.select("id"))

// define a path of length 4 
val motif = hg.find("(root1)-[]->(d1); (d1)-[]->(d2); (d2)-[]->(d3); (d3)-[]->(d4)")


// get only those paths of length 4 that start at the given root
val chain = motif.filter("root1.id = 'FAC001'").select($"root1.id".as("top_id"), $"d3.id".as("parent_id"), $"d4.id".as("child_id"))

然后在shell中尝试:

scala> chain.show
+------+---------+--------+
|top_id|parent_id|child_id|
+------+---------+--------+
|FAC001|   FAC004|  FAC005|
+------+---------+--------+

Graphframes是SparkSQL和DataFrames的混合体 - 你需要包含的就是包

--packages graphframes:graphframes:0.1.0-spark1.6