如何在spark中构建具有多个键的查找功能

时间:2017-07-17 17:17:28

标签: sql scala hadoop apache-spark

我是 spark 的新手,并在上周问了一个类似的问题。它已编译但无法正常工作。所以我真的不知道该怎么做。这是我的问题:我有一个包含3列的表A,像这样

-----------
A1  A1  A3
-----------
a    b   c

和另一个表B这样

------------------------------------
B1  B2  B3  B4  B5  B6  B7  B8  B9
------------------------------------
1   a   3   4   5   b   7   8    c

我的逻辑是:A1 A2 A3是我的钥匙,它对应于表B中的B2 B6 B9。我需要建立一个查找功能,将A1 A2 A3作为键并返回给我B8。

这是我上周试过的:

//getting the data in to dataframe
val clsrowRDD = clsfile.map(_.split("\t")).map(p => Row(p(0),p(1),p(2),p(3),p(4),p(5),p(6),p(7),p(8)))
val clsDataFrame = sqlContext.createDataFrame(clsrowRDD, clsschema)

//mapping the three key with the value
val smallRdd = clsDataFrame.rdd.map{row: Row => (mutable.WrappedArray.make[String](Array(row.getString(1), row.getString(5), row.getString(8))), row.getString(7))}

val lookupMap:Map[mutable.WrappedArray[String], String] = smallRdd.collectAsMap()

//build the look up function
def lookup(lookupMap: Map[mutable.WrappedArray[String],String]) =
udf((input: mutable.WrappedArray[String]) => lookupMap.lift(input))

//call the function
val combinedDF  = mstrDataFrame.withColumn("ENTP_CLS_CD",lookup(lookupMap)($"SRC_SYS_CD",$"ORG_ID",$"ORG_CD"))

此代码编译,但并没有真正返回我需要的结果。我在想它是因为我传入一个数组作为键,我的表中没有数组。但是当我尝试将地图类型更改为Map[(String,String,String),String]时,我不知道你如何在函数中传递它。

非常感谢。

1 个答案:

答案 0 :(得分:1)

如果您尝试为B8A1B2A2B6A3的每个匹配项获得B9值{1}},然后简单的joinselect方法就可以了。 创建查找地图会产生复杂性。

正如您所解释的那样,您必须将数据框df1df2设为

+---+---+---+
|A1 |A2 |A3 |
+---+---+---+
|a  |b  |c  |
+---+---+---+

+---+---+---+---+---+---+---+---+---+
|B1 |B2 |B3 |B4 |B5 |B6 |B7 |B8 |B9 |
+---+---+---+---+---+---+---+---+---+
|1  |a  |3  |4  |5  |b  |7  |8  |c  |
|1  |a  |3  |4  |5  |b  |7  |8  |e  |
+---+---+---+---+---+---+---+---+---+

简单joinselect可以完成

df1.join(df2, $"A1" === $"B2" && $"A2" === $"B6" && $"A3" === $"B9", "inner").select("B8")

应该给你

+---+
|B8 |
+---+
|8  |
+---+

我希望答案很有帮助

<强>更新

根据我在您的问题和评论中所理解的内容,您对如何将array传递到lookup udf函数感到困惑。为此,您可以使用array功能。我修改了几乎完美代码的某些部分以使其正常工作

//mapping the three key with the value
val smallRdd = clsDataFrame.rdd
  .map{row: Row => (mutable.WrappedArray.make[String](Array(row.getString(1), row.getString(5), row.getString(8))), row.getString(7))}

val lookupMap: collection.Map[mutable.WrappedArray[String], String] = smallRdd.collectAsMap()

//build the look up function
def lookup(lookupMap: collection.Map[mutable.WrappedArray[String],String]) =
udf((input: mutable.WrappedArray[String]) => lookupMap.lift(input))

//call the function
val combinedDF  = mstrDataFrame.withColumn("ENTP_CLS_CD",lookup(lookupMap)(array($"SRC_SYS_CD",$"ORG_ID",$"ORG_CD")))

你应该

+----------+------+------+-----------+
|SRC_SYS_CD|ORG_ID|ORG_CD|ENTP_CLS_CD|
+----------+------+------+-----------+
|a         |b     |c     |8          |
+----------+------+------+-----------+