通过MapType列中的查询值与另一列中的键

时间:2018-08-01 18:46:45

标签: scala apache-spark dictionary apache-spark-sql spark-structured-streaming

我有一个带有两列的Spark流数据框架。一个Integer id列和一个MapType列,其中Integer Id作为键,而JSON对象作为值。

---------------------------------------------------------------------------------------------------------------
id             objects
---------------------------------------------------------------------------------------------------------------
1     |    (1 -> {"id" : 1, "type": "jpeg"}, 2 -> {"id" : 2, "type": "gif"}, 3 -> {"id" : 3, "type": "png"})
5     |    (1 -> {"id" : 1, "type": "jpeg"}, 2 -> {"id" : 2, "type": "gif"}, 3 -> {"id" : 3, "type": "png"})
2     |    (1 -> {"id" : 1, "type": "jpeg"}, 2 -> {"id" : 2, "type": "gif"}, 3 -> {"id" : 3, "type": "png"})
---------------------------------------------------------------------------------------------------------------

我想构造一个新数据框,该数据框具有一个包含其键与id列匹配的JSON对象的列。

----------------------------------------------------------------------
objects
----------------------------------------------------------------------
{"id" : 1, "type": "jpeg"}
{"id" : 2, "type": "gif" }
----------------------------------------------------------------------

执行此操作的最佳方法是什么?我实现了一个Scala udf,它执行查找并返回相应的对象值,但是想知道是否可以使用内置的Spark函数来完成相同的操作。

我试图做这样的事情:

df.withColumn("obj", $"objects".getItem($"id"))

但是会引发异常:

java.lang.RuntimeException: Unsupported literal type class org.apache.spark.sql.ColumnName

这很有意义,因为$"id"是列类型。但是,如果执行收集操作,将会导致我希望避免的操作。

1 个答案:

答案 0 :(得分:1)

不需要UDF,您可以使用内置功能来执行此操作。但是,您不能使用getItem,而是可以从Map中获取值,如下所示:

df.withColumn("value", $"objects"($"id"))

要创建新的数据框并删除地图中ID不存在的行,

df.select($"objects"($"id").as("objects")).na.drop

这会给你

+-------------------------+
|objects                  |
+-------------------------+
|{"id": 1, "type": "jpeg"}|
|{"id": 3, "type": "png"} |
+-------------------------+